|
18 | 18 | from __future__ import unicode_literals |
19 | 19 |
|
20 | 20 | from base64 import b64encode |
| 21 | +from itertools import combinations |
21 | 22 |
|
22 | 23 | from IPython.html.services.contents.tests.test_manager import TestContentsManager # noqa |
23 | 24 |
|
@@ -58,6 +59,43 @@ def make_dir(self, api_path): |
58 | 59 | path=api_path, |
59 | 60 | ) |
60 | 61 |
|
| 62 | + def make_populated_dir(self, api_path): |
| 63 | + """ |
| 64 | + Create a directory at api_path with a notebook and a text file. |
| 65 | + """ |
| 66 | + self.make_dir(api_path) |
| 67 | + self.contents_manager.new( |
| 68 | + path='/'.join([api_path, 'nb.ipynb']) |
| 69 | + ) |
| 70 | + self.contents_manager.new( |
| 71 | + path='/'.join([api_path, 'file.txt']) |
| 72 | + ) |
| 73 | + |
| 74 | + def check_populated_dir_files(self, api_path): |
| 75 | + """ |
| 76 | + Check that a directory created with make_populated_dir has a |
| 77 | + notebook and a text file with expected names. |
| 78 | + """ |
| 79 | + dirmodel = self.contents_manager.get(api_path) |
| 80 | + self.assertEqual(dirmodel['path'], api_path) |
| 81 | + self.assertEqual(dirmodel['type'], 'directory') |
| 82 | + for entry in dirmodel['content']: |
| 83 | + # Skip any subdirectories created after the fact. |
| 84 | + if entry['type'] == 'directory': |
| 85 | + continue |
| 86 | + elif entry['type'] == 'file': |
| 87 | + self.assertEqual(entry['name'], 'file.txt') |
| 88 | + self.assertEqual( |
| 89 | + entry['path'], |
| 90 | + '/'.join([api_path, 'file.txt']), |
| 91 | + ) |
| 92 | + elif entry['type'] == 'notebook': |
| 93 | + self.assertEqual(entry['name'], 'nb.ipynb') |
| 94 | + self.assertEqual( |
| 95 | + entry['path'], |
| 96 | + '/'.join([api_path, 'nb.ipynb']), |
| 97 | + ) |
| 98 | + |
61 | 99 | def tearDown(self): |
62 | 100 | drop_testing_db_tables() |
63 | 101 | migrate_testing_db() |
@@ -85,77 +123,59 @@ def test_modified_date(self): |
85 | 123 | self.assertGreater(renamed['last_modified'], saved['last_modified']) |
86 | 124 |
|
87 | 125 | def test_rename_directory(self): |
| 126 | + """ |
| 127 | + Create a directory hierarchy that looks like: |
| 128 | +
|
| 129 | + foo/ |
| 130 | + ... |
| 131 | + bar/ |
| 132 | + ... |
| 133 | + foo/ |
| 134 | + ... |
| 135 | + bar/ |
| 136 | + ... |
| 137 | + bar/ |
| 138 | +
|
| 139 | + then rename /foo/bar -> /foo/bar_changed and verify that all changes |
| 140 | + propagate correctly. |
| 141 | + """ |
88 | 142 | cm = self.contents_manager |
89 | 143 |
|
90 | | - # Create an untitled directory |
91 | | - foo_dir = cm.new_untitled(type='directory') |
92 | | - old_foo_dir_path = foo_dir['path'] |
| 144 | + all_dirs = ['foo', 'bar', 'foo/bar', 'foo/bar/foo', 'foo/bar/foo/bar'] |
| 145 | + unchanged_dirs = all_dirs[:2] |
| 146 | + changed_dirs = all_dirs[2:] |
93 | 147 |
|
94 | | - # Change the path on the model and call cm.update to rename |
95 | | - foo_dir_path = 'foo' |
96 | | - foo_dir['path'] = foo_dir_path |
97 | | - foo_dir = cm.update(foo_dir, old_foo_dir_path) |
| 148 | + for dir_ in all_dirs: |
| 149 | + self.make_populated_dir(dir_) |
| 150 | + self.check_populated_dir_files(dir_) |
98 | 151 |
|
99 | | - # Check that the cm.update returns a model |
100 | | - assert isinstance(foo_dir, dict) |
| 152 | + # Renaming to an extant directory should raise |
| 153 | + for src, dest in combinations(all_dirs, 2): |
| 154 | + with assertRaisesHTTPError(self, 409): |
| 155 | + cm.rename(src, dest) |
101 | 156 |
|
102 | | - # Make sure the untitled directory is gone |
103 | | - self.assertRaises(HTTPError, cm.get, old_foo_dir_path) |
| 157 | + # Verify that we can't create a new notebook in the (nonexistent) |
| 158 | + # target directory |
| 159 | + with assertRaisesHTTPError(self, 404): |
| 160 | + cm.new_untitled('foo/bar_changed', ext='.ipynb') |
104 | 161 |
|
105 | | - # Create a subdirectory |
106 | | - bar_dir = cm.new( |
107 | | - model={'type': 'directory'}, |
108 | | - path='foo/bar', |
109 | | - ) |
110 | | - old_bar_dir_path = bar_dir['path'] |
| 162 | + cm.rename('foo/bar', 'foo/bar_changed') |
111 | 163 |
|
112 | | - # Create a file in the subdirectory |
113 | | - bar_file = cm.new_untitled(path='foo/bar', type='notebook') |
114 | | - old_bar_file_path = bar_file['path'] |
| 164 | + # foo/ and bar/ should be unchanged |
| 165 | + for unchanged in unchanged_dirs: |
| 166 | + self.check_populated_dir_files(unchanged) |
115 | 167 |
|
116 | | - # Create another subdirectory one level deeper. Use 'foo' for the name |
117 | | - # again to catch issues with replacing all instances of a substring |
118 | | - # instead of just the first. |
119 | | - bar2_dir = cm.new( |
120 | | - model={'type': 'directory'}, |
121 | | - path='foo/bar/bar', |
122 | | - ) |
123 | | - old_bar2_dir_path = bar2_dir['path'] |
124 | | - |
125 | | - # Create a file in the two-level deep directory we just created |
126 | | - bar2_file = cm.new_untitled(path=old_bar2_dir_path, type='notebook') |
127 | | - old_bar2_file_path = bar2_file['path'] |
128 | | - |
129 | | - # Change the path of the first bar directory |
130 | | - new_bar_dir_path = 'foo/bar_changed' |
131 | | - bar_dir['path'] = new_bar_dir_path |
132 | | - bar_dir = cm.update(bar_dir, old_bar_dir_path) |
133 | | - self.assertIn('name', bar_dir) |
134 | | - self.assertIn('path', bar_dir) |
135 | | - self.assertEqual(bar_dir['name'], 'bar_changed') |
136 | | - |
137 | | - # Make sure calling cm.get on any old paths throws an exception |
138 | | - self.assertRaises(HTTPError, cm.get, old_bar_dir_path) |
139 | | - self.assertRaises(HTTPError, cm.get, old_bar2_dir_path) |
140 | | - self.assertRaises(HTTPError, cm.get, old_bar_file_path) |
141 | | - self.assertRaises(HTTPError, cm.get, old_bar2_file_path) |
142 | | - |
143 | | - def try_get_new_path(full_old_path): |
144 | | - # replace the first occurence of the old path with the new one |
145 | | - new_path = full_old_path.replace( |
146 | | - old_bar_dir_path, |
147 | | - new_bar_dir_path, |
148 | | - 1 |
| 168 | + # foo/bar/ and subdirectories should have leading prefixes changed |
| 169 | + for changed_dirname in changed_dirs: |
| 170 | + with assertRaisesHTTPError(self, 404): |
| 171 | + cm.get(changed_dirname) |
| 172 | + new_dirname = changed_dirname.replace( |
| 173 | + 'foo/bar', 'foo/bar_changed', 1 |
149 | 174 | ) |
150 | | - new_model = cm.get(new_path) |
151 | | - self.assertIn('name', new_model) |
152 | | - self.assertIn('path', new_model) |
153 | | - |
154 | | - # Make sure the directories and files can be found at their new paths |
155 | | - try_get_new_path(foo_dir_path) # top level foo dir should be unchanged |
156 | | - try_get_new_path(old_bar_file_path) |
157 | | - try_get_new_path(old_bar2_dir_path) |
158 | | - try_get_new_path(old_bar2_file_path) |
| 175 | + self.check_populated_dir_files(new_dirname) |
| 176 | + |
| 177 | + # Verify that we can now create a new notebook in the changed directory |
| 178 | + cm.new_untitled('foo/bar_changed', ext='.ipynb') |
159 | 179 |
|
160 | 180 | def test_max_file_size(self): |
161 | 181 |
|
|
0 commit comments