pyglove 0.5.0.dev202510020810__py3-none-any.whl → 0.5.0.dev202512280810__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyglove might be problematic. Click here for more details.
- pyglove/core/geno/base.py +7 -3
- pyglove/core/io/file_system.py +452 -2
- pyglove/core/io/file_system_test.py +442 -0
- pyglove/core/monitoring.py +213 -90
- pyglove/core/monitoring_test.py +82 -29
- pyglove/core/symbolic/__init__.py +7 -0
- pyglove/core/symbolic/base.py +89 -35
- pyglove/core/symbolic/base_test.py +3 -3
- pyglove/core/symbolic/dict.py +31 -12
- pyglove/core/symbolic/dict_test.py +49 -0
- pyglove/core/symbolic/list.py +17 -3
- pyglove/core/symbolic/list_test.py +24 -2
- pyglove/core/symbolic/object.py +3 -1
- pyglove/core/symbolic/object_test.py +13 -10
- pyglove/core/symbolic/ref.py +19 -7
- pyglove/core/symbolic/ref_test.py +94 -7
- pyglove/core/symbolic/unknown_symbols.py +147 -0
- pyglove/core/symbolic/unknown_symbols_test.py +100 -0
- pyglove/core/typing/annotation_conversion.py +8 -1
- pyglove/core/typing/annotation_conversion_test.py +14 -19
- pyglove/core/typing/class_schema.py +24 -1
- pyglove/core/typing/json_schema.py +221 -8
- pyglove/core/typing/json_schema_test.py +508 -12
- pyglove/core/typing/type_conversion.py +17 -3
- pyglove/core/typing/type_conversion_test.py +7 -2
- pyglove/core/typing/value_specs.py +5 -1
- pyglove/core/typing/value_specs_test.py +5 -0
- pyglove/core/utils/__init__.py +1 -0
- pyglove/core/utils/contextual.py +9 -4
- pyglove/core/utils/contextual_test.py +10 -0
- pyglove/core/utils/json_conversion.py +360 -63
- pyglove/core/utils/json_conversion_test.py +146 -13
- pyglove/core/views/html/controls/tab.py +33 -0
- pyglove/core/views/html/controls/tab_test.py +37 -0
- pyglove/ext/evolution/base_test.py +1 -1
- {pyglove-0.5.0.dev202510020810.dist-info → pyglove-0.5.0.dev202512280810.dist-info}/METADATA +8 -1
- {pyglove-0.5.0.dev202510020810.dist-info → pyglove-0.5.0.dev202512280810.dist-info}/RECORD +40 -38
- {pyglove-0.5.0.dev202510020810.dist-info → pyglove-0.5.0.dev202512280810.dist-info}/WHEEL +0 -0
- {pyglove-0.5.0.dev202510020810.dist-info → pyglove-0.5.0.dev202512280810.dist-info}/licenses/LICENSE +0 -0
- {pyglove-0.5.0.dev202510020810.dist-info → pyglove-0.5.0.dev202512280810.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import datetime
|
|
15
16
|
import os
|
|
16
17
|
import pathlib
|
|
18
|
+
import shutil
|
|
17
19
|
import tempfile
|
|
20
|
+
import time
|
|
18
21
|
import unittest
|
|
22
|
+
from unittest import mock
|
|
23
|
+
import fsspec
|
|
19
24
|
from pyglove.core.io import file_system
|
|
20
25
|
|
|
21
26
|
|
|
@@ -82,6 +87,111 @@ class StdFileSystemTest(unittest.TestCase):
|
|
|
82
87
|
fs.rmdirs(os.path.join(dir_a, 'b/c'))
|
|
83
88
|
self.assertEqual(sorted(fs.listdir(dir_a)), ['file1']) # pylint: disable=g-generic-assert
|
|
84
89
|
|
|
90
|
+
def test_rename(self):
|
|
91
|
+
tmp_dir = tempfile.mkdtemp()
|
|
92
|
+
fs = file_system.StdFileSystem()
|
|
93
|
+
|
|
94
|
+
_ = fs.mkdirs(os.path.join(tmp_dir, 'a/b'))
|
|
95
|
+
file_foo = os.path.join(tmp_dir, 'a/foo.txt')
|
|
96
|
+
file_bar = os.path.join(tmp_dir, 'a/bar.txt')
|
|
97
|
+
|
|
98
|
+
with fs.open(file_foo, 'w') as f:
|
|
99
|
+
f.write('foo')
|
|
100
|
+
with fs.open(file_bar, 'w') as f:
|
|
101
|
+
f.write('bar')
|
|
102
|
+
|
|
103
|
+
# Rename file to a new name.
|
|
104
|
+
file_foo_new = os.path.join(tmp_dir, 'a/foo-new.txt')
|
|
105
|
+
fs.rename(file_foo, file_foo_new)
|
|
106
|
+
self.assertFalse(fs.exists(file_foo))
|
|
107
|
+
self.assertTrue(fs.exists(file_foo_new))
|
|
108
|
+
|
|
109
|
+
# Rename file to an existing file name.
|
|
110
|
+
fs.rename(file_foo_new, file_bar)
|
|
111
|
+
self.assertFalse(fs.exists(file_foo_new))
|
|
112
|
+
with fs.open(file_bar, 'r') as f:
|
|
113
|
+
self.assertEqual(f.read(), 'foo')
|
|
114
|
+
|
|
115
|
+
# Rename directory to a new name.
|
|
116
|
+
dir_b = os.path.join(tmp_dir, 'a/b')
|
|
117
|
+
dir_c = os.path.join(tmp_dir, 'a/c')
|
|
118
|
+
fs.rename(dir_b, dir_c)
|
|
119
|
+
self.assertFalse(fs.exists(dir_b))
|
|
120
|
+
self.assertTrue(fs.exists(dir_c))
|
|
121
|
+
self.assertTrue(fs.isdir(dir_c))
|
|
122
|
+
|
|
123
|
+
# Rename directory to an existing empty directory.
|
|
124
|
+
dir_d = os.path.join(tmp_dir, 'a/d')
|
|
125
|
+
fs.mkdirs(dir_d)
|
|
126
|
+
fs.rename(dir_c, dir_d)
|
|
127
|
+
self.assertFalse(fs.exists(dir_c))
|
|
128
|
+
self.assertTrue(fs.exists(dir_d))
|
|
129
|
+
|
|
130
|
+
# Rename directory to a non-empty directory.
|
|
131
|
+
dir_x = os.path.join(tmp_dir, 'x')
|
|
132
|
+
dir_a = os.path.join(tmp_dir, 'a')
|
|
133
|
+
fs.mkdirs(os.path.join(dir_x, 'y'))
|
|
134
|
+
with self.assertRaises(OSError):
|
|
135
|
+
fs.rename(dir_a, dir_x)
|
|
136
|
+
self.assertTrue(fs.exists(dir_a))
|
|
137
|
+
self.assertTrue(fs.exists(os.path.join(dir_x, 'y')))
|
|
138
|
+
|
|
139
|
+
# Errors
|
|
140
|
+
dir_u = os.path.join(tmp_dir, 'u')
|
|
141
|
+
dir_u_v = os.path.join(dir_u, 'v')
|
|
142
|
+
file_u_a = os.path.join(dir_u, 'a.txt')
|
|
143
|
+
fs.mkdirs(dir_u_v)
|
|
144
|
+
with fs.open(file_u_a, 'w') as f:
|
|
145
|
+
f.write('a')
|
|
146
|
+
|
|
147
|
+
with self.assertRaises((OSError, NotADirectoryError)):
|
|
148
|
+
fs.rename(dir_u, file_u_a)
|
|
149
|
+
|
|
150
|
+
with self.assertRaises(IsADirectoryError):
|
|
151
|
+
fs.rename(file_u_a, dir_u_v)
|
|
152
|
+
|
|
153
|
+
with self.assertRaises(FileNotFoundError):
|
|
154
|
+
fs.rename(
|
|
155
|
+
os.path.join(tmp_dir, 'non-existent'),
|
|
156
|
+
os.path.join(tmp_dir, 'y')
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def test_copy(self):
|
|
160
|
+
tmp_dir = tempfile.mkdtemp()
|
|
161
|
+
fs = file_system.StdFileSystem()
|
|
162
|
+
foo_txt = os.path.join(tmp_dir, 'foo.txt')
|
|
163
|
+
bar_txt = os.path.join(tmp_dir, 'bar.txt')
|
|
164
|
+
sub_dir = os.path.join(tmp_dir, 'sub')
|
|
165
|
+
sub_foo_txt = os.path.join(sub_dir, 'foo.txt')
|
|
166
|
+
|
|
167
|
+
with fs.open(foo_txt, 'w') as f:
|
|
168
|
+
f.write('hello')
|
|
169
|
+
fs.copy(foo_txt, bar_txt)
|
|
170
|
+
with fs.open(bar_txt) as f:
|
|
171
|
+
self.assertEqual(f.read(), 'hello')
|
|
172
|
+
fs.mkdir(sub_dir)
|
|
173
|
+
fs.copy(foo_txt, sub_dir)
|
|
174
|
+
with fs.open(sub_foo_txt) as f:
|
|
175
|
+
self.assertEqual(f.read(), 'hello')
|
|
176
|
+
with fs.open(foo_txt, 'w') as f:
|
|
177
|
+
f.write('overwrite')
|
|
178
|
+
fs.copy(foo_txt, bar_txt)
|
|
179
|
+
with fs.open(bar_txt) as f:
|
|
180
|
+
self.assertEqual(f.read(), 'overwrite')
|
|
181
|
+
shutil.rmtree(tmp_dir)
|
|
182
|
+
|
|
183
|
+
def test_getctime_getmtime(self):
|
|
184
|
+
tmp_dir = tempfile.mkdtemp()
|
|
185
|
+
fs = file_system.StdFileSystem()
|
|
186
|
+
file1 = os.path.join(tmp_dir, 'file1')
|
|
187
|
+
with fs.open(file1, 'w') as f:
|
|
188
|
+
f.write('hello')
|
|
189
|
+
ctime = fs.getctime(file1)
|
|
190
|
+
mtime = fs.getmtime(file1)
|
|
191
|
+
self.assertLess(0, ctime)
|
|
192
|
+
self.assertLessEqual(ctime, mtime)
|
|
193
|
+
shutil.rmtree(tmp_dir)
|
|
194
|
+
|
|
85
195
|
|
|
86
196
|
class MemoryFileSystemTest(unittest.TestCase):
|
|
87
197
|
|
|
@@ -180,6 +290,145 @@ class MemoryFileSystemTest(unittest.TestCase):
|
|
|
180
290
|
fs.rmdirs(os.path.join(dir_a, 'b/c'))
|
|
181
291
|
self.assertEqual(fs.listdir(dir_a), ['file1']) # pylint: disable=g-generic-assert
|
|
182
292
|
|
|
293
|
+
def test_glob(self):
|
|
294
|
+
fs = file_system.MemoryFileSystem()
|
|
295
|
+
fs.mkdirs('/mem/a/b/c')
|
|
296
|
+
with fs.open('/mem/a/foo.txt', 'w') as f:
|
|
297
|
+
f.write('foo')
|
|
298
|
+
with fs.open('/mem/a/bar.json', 'w') as f:
|
|
299
|
+
f.write('bar')
|
|
300
|
+
with fs.open('/mem/a/b/baz.txt', 'w') as f:
|
|
301
|
+
f.write('baz')
|
|
302
|
+
|
|
303
|
+
self.assertEqual(
|
|
304
|
+
sorted(fs.glob('/mem/a/*')),
|
|
305
|
+
['/mem/a/b', '/mem/a/b/baz.txt', '/mem/a/b/c',
|
|
306
|
+
'/mem/a/bar.json', '/mem/a/foo.txt'])
|
|
307
|
+
self.assertEqual(
|
|
308
|
+
sorted(fs.glob('/mem/a/*.txt')),
|
|
309
|
+
['/mem/a/b/baz.txt', '/mem/a/foo.txt'])
|
|
310
|
+
self.assertEqual(
|
|
311
|
+
sorted(fs.glob('/mem/a/b/*')),
|
|
312
|
+
['/mem/a/b/baz.txt', '/mem/a/b/c'])
|
|
313
|
+
self.assertEqual(fs.glob('/mem/a/b/*.txt'), ['/mem/a/b/baz.txt'])
|
|
314
|
+
self.assertEqual(fs.glob('/mem/a/b/c/*'), [])
|
|
315
|
+
self.assertEqual(fs.glob('/mem/a/???.txt'), ['/mem/a/foo.txt'])
|
|
316
|
+
self.assertEqual(fs.glob('/mem/a/bar.*'), ['/mem/a/bar.json'])
|
|
317
|
+
self.assertEqual(
|
|
318
|
+
sorted(fs.glob('/mem/a/*.*')),
|
|
319
|
+
['/mem/a/b/baz.txt', '/mem/a/bar.json', '/mem/a/foo.txt'])
|
|
320
|
+
|
|
321
|
+
def test_rename(self):
|
|
322
|
+
fs = file_system.MemoryFileSystem()
|
|
323
|
+
fs.mkdirs('/mem/a/b')
|
|
324
|
+
with fs.open('/mem/a/foo.txt', 'w') as f:
|
|
325
|
+
f.write('foo')
|
|
326
|
+
with fs.open('/mem/a/bar.txt', 'w') as f:
|
|
327
|
+
f.write('bar')
|
|
328
|
+
|
|
329
|
+
# Rename file to a new name.
|
|
330
|
+
fs.rename('/mem/a/foo.txt', '/mem/a/foo-new.txt')
|
|
331
|
+
self.assertFalse(fs.exists('/mem/a/foo.txt'))
|
|
332
|
+
self.assertTrue(fs.exists('/mem/a/foo-new.txt'))
|
|
333
|
+
|
|
334
|
+
# Rename file to an existing file name.
|
|
335
|
+
fs.rename('/mem/a/foo-new.txt', '/mem/a/bar.txt')
|
|
336
|
+
self.assertFalse(fs.exists('/mem/a/foo-new.txt'))
|
|
337
|
+
with fs.open('/mem/a/bar.txt', 'r') as f:
|
|
338
|
+
self.assertEqual(f.read(), 'foo')
|
|
339
|
+
|
|
340
|
+
# Rename directory to a new name.
|
|
341
|
+
fs.rename('/mem/a/b', '/mem/a/c')
|
|
342
|
+
self.assertFalse(fs.exists('/mem/a/b'))
|
|
343
|
+
self.assertTrue(fs.exists('/mem/a/c'))
|
|
344
|
+
self.assertTrue(fs.isdir('/mem/a/c'))
|
|
345
|
+
|
|
346
|
+
# Rename directory to an existing empty directory.
|
|
347
|
+
fs.mkdirs('/mem/a/d')
|
|
348
|
+
fs.rename('/mem/a/c', '/mem/a/d')
|
|
349
|
+
self.assertFalse(fs.exists('/mem/a/c'))
|
|
350
|
+
self.assertTrue(fs.exists('/mem/a/d'))
|
|
351
|
+
|
|
352
|
+
# Rename directory to a non-empty directory.
|
|
353
|
+
fs.mkdirs('/mem/x/y')
|
|
354
|
+
with self.assertRaisesRegex(OSError, "Directory not empty: '/mem/x'"):
|
|
355
|
+
fs.rename('/mem/a', '/mem/x')
|
|
356
|
+
self.assertTrue(fs.exists('/mem/a'))
|
|
357
|
+
self.assertTrue(fs.exists('/mem/x/y'))
|
|
358
|
+
|
|
359
|
+
# Errors
|
|
360
|
+
fs.mkdirs('/mem/u/v')
|
|
361
|
+
with fs.open('/mem/u/a.txt', 'w') as f:
|
|
362
|
+
f.write('a')
|
|
363
|
+
|
|
364
|
+
with self.assertRaisesRegex(
|
|
365
|
+
OSError, "Cannot move directory '/mem/u' to a subdirectory of itself"):
|
|
366
|
+
fs.rename('/mem/u', '/mem/u/v/w')
|
|
367
|
+
|
|
368
|
+
with self.assertRaisesRegex(
|
|
369
|
+
NotADirectoryError,
|
|
370
|
+
"Cannot rename directory '/mem/u' to non-directory '/mem/u/a.txt'"):
|
|
371
|
+
fs.rename('/mem/u', '/mem/u/a.txt')
|
|
372
|
+
|
|
373
|
+
with self.assertRaisesRegex(
|
|
374
|
+
IsADirectoryError,
|
|
375
|
+
"Cannot rename non-directory '/mem/u/a.txt' to directory '/mem/u/v'"):
|
|
376
|
+
fs.rename('/mem/u/a.txt', '/mem/u/v')
|
|
377
|
+
|
|
378
|
+
with self.assertRaises(FileNotFoundError):
|
|
379
|
+
fs.rename('/mem/non-existent', '/mem/y')
|
|
380
|
+
|
|
381
|
+
def test_copy(self):
|
|
382
|
+
fs = file_system.MemoryFileSystem()
|
|
383
|
+
fs.mkdirs('/mem/a')
|
|
384
|
+
with fs.open('/mem/a/foo.txt', 'w') as f:
|
|
385
|
+
f.write('hello')
|
|
386
|
+
fs.copy('/mem/a/foo.txt', '/mem/a/bar.txt')
|
|
387
|
+
self.assertEqual(fs.open('/mem/a/bar.txt').read(), 'hello')
|
|
388
|
+
fs.mkdir('/mem/b')
|
|
389
|
+
fs.copy('/mem/a/foo.txt', '/mem/b')
|
|
390
|
+
self.assertEqual(fs.open('/mem/b/foo.txt').read(), 'hello')
|
|
391
|
+
with fs.open('/mem/a/foo.txt', 'w') as f:
|
|
392
|
+
f.write('overwrite')
|
|
393
|
+
fs.copy('/mem/a/foo.txt', '/mem/a/bar.txt')
|
|
394
|
+
self.assertEqual(fs.open('/mem/a/bar.txt').read(), 'overwrite')
|
|
395
|
+
|
|
396
|
+
# Test exceptions
|
|
397
|
+
with self.assertRaises(FileNotFoundError):
|
|
398
|
+
fs.copy('/mem/non-existent', '/mem/y')
|
|
399
|
+
with self.assertRaisesRegex(IsADirectoryError, '/mem/a'):
|
|
400
|
+
fs.copy('/mem/a', '/mem/y')
|
|
401
|
+
|
|
402
|
+
fs.mkdirs('/mem/c/foo.txt')
|
|
403
|
+
with self.assertRaisesRegex(IsADirectoryError, '/mem/c/foo.txt'):
|
|
404
|
+
fs.copy('/mem/a/foo.txt', '/mem/c')
|
|
405
|
+
|
|
406
|
+
def test_getctime_getmtime(self):
|
|
407
|
+
fs = file_system.MemoryFileSystem()
|
|
408
|
+
fs.mkdirs('/mem/a')
|
|
409
|
+
file1 = '/mem/file1_times'
|
|
410
|
+
with fs.open(file1, 'w') as f:
|
|
411
|
+
f.write('hello')
|
|
412
|
+
ctime = fs.getctime(file1)
|
|
413
|
+
mtime = fs.getmtime(file1)
|
|
414
|
+
self.assertLess(0, ctime)
|
|
415
|
+
self.assertLess(ctime, mtime)
|
|
416
|
+
time.sleep(0.01)
|
|
417
|
+
with fs.open(file1, 'w') as f:
|
|
418
|
+
f.write('world')
|
|
419
|
+
self.assertEqual(fs.getctime(file1), ctime)
|
|
420
|
+
self.assertLess(mtime, fs.getmtime(file1))
|
|
421
|
+
|
|
422
|
+
with self.assertRaises(IsADirectoryError):
|
|
423
|
+
fs.getctime('/mem/a')
|
|
424
|
+
with self.assertRaises(FileNotFoundError):
|
|
425
|
+
fs.getctime('/mem/non_existent')
|
|
426
|
+
|
|
427
|
+
with self.assertRaises(IsADirectoryError):
|
|
428
|
+
fs.getmtime('/mem/a')
|
|
429
|
+
with self.assertRaises(FileNotFoundError):
|
|
430
|
+
fs.getmtime('/mem/non_existent')
|
|
431
|
+
|
|
183
432
|
|
|
184
433
|
class FileIoApiTest(unittest.TestCase):
|
|
185
434
|
|
|
@@ -217,6 +466,14 @@ class FileIoApiTest(unittest.TestCase):
|
|
|
217
466
|
file_system.rm(file2)
|
|
218
467
|
self.assertFalse(file_system.path_exists(file2))
|
|
219
468
|
|
|
469
|
+
# Test glob with standard file system.
|
|
470
|
+
glob_dir = os.path.join(tempfile.mkdtemp(), 'glob')
|
|
471
|
+
file_system.mkdirs(os.path.join(glob_dir, 'a/b'))
|
|
472
|
+
file_system.writefile(os.path.join(glob_dir, 'a/foo.txt'), 'foo')
|
|
473
|
+
self.assertEqual(
|
|
474
|
+
sorted(file_system.glob(os.path.join(glob_dir, 'a/*'))),
|
|
475
|
+
[os.path.join(glob_dir, 'a/b'), os.path.join(glob_dir, 'a/foo.txt')])
|
|
476
|
+
|
|
220
477
|
def test_memory_filesystem(self):
|
|
221
478
|
file1 = pathlib.Path('/mem/file1')
|
|
222
479
|
with self.assertRaises(FileNotFoundError):
|
|
@@ -248,6 +505,191 @@ class FileIoApiTest(unittest.TestCase):
|
|
|
248
505
|
file_system.rm(file2)
|
|
249
506
|
self.assertFalse(file_system.path_exists(file2))
|
|
250
507
|
|
|
508
|
+
# Test glob with memory file system.
|
|
509
|
+
file_system.mkdirs('/mem/g/a/b')
|
|
510
|
+
file_system.writefile('/mem/g/a/foo.txt', 'foo')
|
|
511
|
+
file_system.rename('/mem/g/a/foo.txt', '/mem/g/a/foo2.txt')
|
|
512
|
+
file_system.writefile('/mem/g/a/b/bar.txt', 'bar')
|
|
513
|
+
self.assertEqual(
|
|
514
|
+
sorted(file_system.glob('/mem/g/a/*')),
|
|
515
|
+
['/mem/g/a/b', '/mem/g/a/b/bar.txt', '/mem/g/a/foo2.txt'])
|
|
516
|
+
|
|
517
|
+
def test_getctime_getmtime(self):
|
|
518
|
+
# Test with standard file system.
|
|
519
|
+
std_file = os.path.join(tempfile.mkdtemp(), 'file_ctime_mtime')
|
|
520
|
+
file_system.writefile(std_file, 'foo')
|
|
521
|
+
self.assertLess(0, file_system.getctime(std_file))
|
|
522
|
+
self.assertLess(0, file_system.getmtime(std_file))
|
|
523
|
+
|
|
524
|
+
# Test with memory file system.
|
|
525
|
+
mem_file = '/mem/file_ctime_mtime'
|
|
526
|
+
file_system.writefile(mem_file, 'foo')
|
|
527
|
+
self.assertLess(0, file_system.getctime(mem_file))
|
|
528
|
+
self.assertLess(0, file_system.getmtime(mem_file))
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
class FsspecFileSystemTest(unittest.TestCase):
|
|
532
|
+
|
|
533
|
+
def setUp(self):
|
|
534
|
+
super().setUp()
|
|
535
|
+
self.fs = fsspec.filesystem('memory')
|
|
536
|
+
self.fs.pipe('memory:///a/b/c', b'abc')
|
|
537
|
+
self.fs.pipe('memory:///a/b/d', b'abd')
|
|
538
|
+
self.fs.mkdir('memory:///a/e')
|
|
539
|
+
self.tmp_dir = tempfile.mkdtemp()
|
|
540
|
+
|
|
541
|
+
def tearDown(self):
|
|
542
|
+
super().tearDown()
|
|
543
|
+
fsspec.filesystem('memory').rm('/', recursive=True)
|
|
544
|
+
shutil.rmtree(self.tmp_dir)
|
|
545
|
+
|
|
546
|
+
def test_read_file(self):
|
|
547
|
+
self.assertEqual(file_system.readfile('memory:///a/b/c', mode='rb'), b'abc')
|
|
548
|
+
with file_system.open('memory:///a/b/d', 'rb') as f:
|
|
549
|
+
self.assertEqual(f.read(), b'abd')
|
|
550
|
+
|
|
551
|
+
def test_fsspec_file_ops(self):
|
|
552
|
+
file_system.writefile('memory:///f', b'hello\nworld\n', mode='wb')
|
|
553
|
+
with file_system.open('memory:///f', 'rb') as f:
|
|
554
|
+
self.assertIsInstance(f, file_system.FsspecFile)
|
|
555
|
+
self.assertEqual(f.readline(), b'hello\n')
|
|
556
|
+
self.assertEqual(f.tell(), 6)
|
|
557
|
+
self.assertEqual(f.seek(8), 8)
|
|
558
|
+
self.assertEqual(f.read(), b'rld\n')
|
|
559
|
+
f.flush()
|
|
560
|
+
|
|
561
|
+
def test_write_file(self):
|
|
562
|
+
file_system.writefile('memory:///a/b/e', b'abe', mode='wb')
|
|
563
|
+
self.assertTrue(self.fs.exists('memory:///a/b/e'))
|
|
564
|
+
self.assertEqual(self.fs.cat('memory:///a/b/e'), b'abe')
|
|
565
|
+
|
|
566
|
+
def test_exists(self):
|
|
567
|
+
self.assertTrue(file_system.path_exists('memory:///a/b/c'))
|
|
568
|
+
self.assertFalse(file_system.path_exists('memory:///a/b/nonexist'))
|
|
569
|
+
|
|
570
|
+
def test_isdir(self):
|
|
571
|
+
self.assertTrue(file_system.isdir('memory:///a/b'))
|
|
572
|
+
self.assertTrue(file_system.isdir('memory:///a/e'))
|
|
573
|
+
self.assertFalse(file_system.isdir('memory:///a/b/c'))
|
|
574
|
+
|
|
575
|
+
def test_listdir(self):
|
|
576
|
+
self.assertCountEqual(file_system.listdir('memory:///a'), ['b', 'e'])
|
|
577
|
+
self.assertCountEqual(file_system.listdir('memory:///a/b'), ['c', 'd'])
|
|
578
|
+
|
|
579
|
+
def test_glob(self):
|
|
580
|
+
self.assertCountEqual(
|
|
581
|
+
file_system.glob('memory:///a/b/*'),
|
|
582
|
+
['memory:///a/b/c', 'memory:///a/b/d']
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
def test_mkdir(self):
|
|
586
|
+
file_system.mkdir('memory:///a/f')
|
|
587
|
+
self.assertTrue(self.fs.isdir('memory:///a/f'))
|
|
588
|
+
|
|
589
|
+
def test_mkdirs(self):
|
|
590
|
+
file_system.mkdirs('memory:///g/h/i')
|
|
591
|
+
self.assertTrue(self.fs.isdir('memory:///g/h/i'))
|
|
592
|
+
|
|
593
|
+
def test_rm(self):
|
|
594
|
+
file_system.rm('memory:///a/b/c')
|
|
595
|
+
self.assertFalse(self.fs.exists('memory:///a/b/c'))
|
|
596
|
+
|
|
597
|
+
def test_rename(self):
|
|
598
|
+
file_system.rename('memory:///a/b/c', 'memory:///a/b/c_new')
|
|
599
|
+
self.assertFalse(self.fs.exists('memory:///a/b/c'))
|
|
600
|
+
self.assertTrue(self.fs.exists('memory:///a/b/c_new'))
|
|
601
|
+
with self.assertRaisesRegex(ValueError, 'Rename across different'):
|
|
602
|
+
file_system.rename('memory:///a/b/c_new', 'file:///a/b/c_d')
|
|
603
|
+
|
|
604
|
+
def test_chmod(self):
|
|
605
|
+
mock_fs = mock.Mock()
|
|
606
|
+
mock_fs.chmod = mock.Mock()
|
|
607
|
+
with mock.patch('fsspec.core.url_to_fs', return_value=(mock_fs, 'path')):
|
|
608
|
+
file_system.chmod('protocol:///path', 0o777)
|
|
609
|
+
mock_fs.chmod.assert_called_once_with('path', 0o777)
|
|
610
|
+
|
|
611
|
+
def test_rmdir(self):
|
|
612
|
+
file_system.rmdir('memory:///a/e')
|
|
613
|
+
self.assertFalse(self.fs.exists('memory:///a/e'))
|
|
614
|
+
|
|
615
|
+
def test_rmdirs(self):
|
|
616
|
+
file_system.mkdirs('memory:///x/y/z')
|
|
617
|
+
self.assertTrue(file_system.isdir('memory:///x/y/z'))
|
|
618
|
+
file_system.rmdirs('memory:///x')
|
|
619
|
+
self.assertFalse(file_system.path_exists('memory:///x'))
|
|
620
|
+
|
|
621
|
+
def test_copy(self):
|
|
622
|
+
# same FS copy
|
|
623
|
+
file_system.copy('memory:///a/b/c', 'memory:///a/f')
|
|
624
|
+
self.assertEqual(file_system.readfile('memory:///a/f', mode='rb'), b'abc')
|
|
625
|
+
|
|
626
|
+
# same FS copy to dir
|
|
627
|
+
file_system.copy('memory:///a/b/d', 'memory:///a/e')
|
|
628
|
+
self.assertEqual(file_system.readfile('memory:///a/e/d', mode='rb'), b'abd')
|
|
629
|
+
|
|
630
|
+
# cross FS copy: memory to local
|
|
631
|
+
local_path = os.path.join(self.tmp_dir, 'test.txt')
|
|
632
|
+
file_system.copy('memory:///a/b/c', f'file://{local_path}')
|
|
633
|
+
self.assertEqual(file_system.readfile(local_path, mode='rb'), b'abc')
|
|
634
|
+
|
|
635
|
+
# cross FS copy: local to memory
|
|
636
|
+
file_system.copy(f'file://{local_path}', 'memory:///a/g')
|
|
637
|
+
self.assertEqual(file_system.readfile('memory:///a/g', mode='rb'), b'abc')
|
|
638
|
+
|
|
639
|
+
def test_getctime_getmtime(self):
|
|
640
|
+
self.fs.touch('memory:///a/b/c_time')
|
|
641
|
+
now = datetime.datetime.now()
|
|
642
|
+
with mock.patch.object(self.fs, 'created', return_value=now):
|
|
643
|
+
self.assertEqual(
|
|
644
|
+
file_system.getctime('memory:///a/b/c_time'), now.timestamp()
|
|
645
|
+
)
|
|
646
|
+
with mock.patch.object(self.fs, 'modified', return_value=now):
|
|
647
|
+
self.assertEqual(
|
|
648
|
+
file_system.getmtime('memory:///a/b/c_time'), now.timestamp()
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
with mock.patch.object(self.fs, 'created', return_value=None):
|
|
652
|
+
with self.assertRaisesRegex(OSError, 'c-time is not available'):
|
|
653
|
+
file_system.getctime('memory:///a/b/c_time')
|
|
654
|
+
|
|
655
|
+
with mock.patch.object(self.fs, 'modified', return_value=None):
|
|
656
|
+
with self.assertRaisesRegex(OSError, 'm-time is not available'):
|
|
657
|
+
file_system.getmtime('memory:///a/b/c_time')
|
|
658
|
+
|
|
659
|
+
def test_fsspec_uri_catcher(self):
|
|
660
|
+
with mock.patch.object(
|
|
661
|
+
file_system.FsspecFileSystem, 'exists', return_value=True
|
|
662
|
+
) as mock_fsspec_exists:
|
|
663
|
+
# We use a protocol that is not registered in
|
|
664
|
+
# fsspec.available_protocols() to make sure _FsspecUriCatcher is used.
|
|
665
|
+
self.assertTrue(file_system.path_exists('some-proto://foo'))
|
|
666
|
+
mock_fsspec_exists.assert_called_once_with('some-proto://foo')
|
|
667
|
+
|
|
668
|
+
# For full coverage of _FsspecUriCatcher.get_fs returning StdFileSystem,
|
|
669
|
+
# we need to test a non-URI path that doesn't match other prefixes.
|
|
670
|
+
# We mock StdFileSystem.exists to check if it's called.
|
|
671
|
+
with mock.patch.object(
|
|
672
|
+
file_system.StdFileSystem, 'exists', return_value=True
|
|
673
|
+
) as mock_std_exists:
|
|
674
|
+
self.assertTrue(file_system.path_exists('/foo/bar/baz'))
|
|
675
|
+
mock_std_exists.assert_called_once_with('/foo/bar/baz')
|
|
676
|
+
|
|
677
|
+
with mock.patch.object(
|
|
678
|
+
file_system.FsspecFileSystem, 'rename', return_value=None
|
|
679
|
+
) as mock_fsspec_rename:
|
|
680
|
+
file_system.rename('some-proto://foo', 'some-proto://bar')
|
|
681
|
+
mock_fsspec_rename.assert_called_once_with(
|
|
682
|
+
'some-proto://foo', 'some-proto://bar'
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
with mock.patch.object(
|
|
686
|
+
file_system.FsspecFileSystem, 'copy', return_value=None
|
|
687
|
+
) as mock_fsspec_copy:
|
|
688
|
+
file_system.copy('some-proto://foo', 'some-proto://bar')
|
|
689
|
+
mock_fsspec_copy.assert_called_once_with(
|
|
690
|
+
'some-proto://foo', 'some-proto://bar'
|
|
691
|
+
)
|
|
692
|
+
|
|
251
693
|
|
|
252
694
|
if __name__ == '__main__':
|
|
253
695
|
unittest.main()
|