pyglove 0.5.0.dev202511300809__py3-none-any.whl → 0.5.0.dev202601060812__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.
@@ -14,11 +14,13 @@
14
14
  """Pluggable file system."""
15
15
 
16
16
  import abc
17
+ import datetime
17
18
  import fnmatch
18
19
  import glob as std_glob
19
20
  import io
20
21
  import os
21
22
  import re
23
+ import shutil
22
24
  from typing import Any, Literal, Optional, Union
23
25
 
24
26
 
@@ -99,6 +101,14 @@ class FileSystem(metaclass=abc.ABCMeta):
99
101
  def isdir(self, path: Union[str, os.PathLike[str]]) -> bool:
100
102
  """Returns True if a path is a directory."""
101
103
 
104
+ @abc.abstractmethod
105
+ def getctime(self, path: Union[str, os.PathLike[str]]) -> float:
106
+ """Returns the creation time of a file."""
107
+
108
+ @abc.abstractmethod
109
+ def getmtime(self, path: Union[str, os.PathLike[str]]) -> float:
110
+ """Returns the last modification time of a file."""
111
+
102
112
  @abc.abstractmethod
103
113
  def mkdir(
104
114
  self, path: Union[str, os.PathLike[str]], mode: int = 0o777
@@ -134,6 +144,14 @@ class FileSystem(metaclass=abc.ABCMeta):
134
144
  def rmdirs(self, path: Union[str, os.PathLike[str]]) -> None:
135
145
  """Removes a directory chain based on a path."""
136
146
 
147
+ @abc.abstractmethod
148
+ def copy(
149
+ self,
150
+ oldpath: Union[str, os.PathLike[str]],
151
+ newpath: Union[str, os.PathLike[str]],
152
+ ) -> None:
153
+ """Copies a file to a new path."""
154
+
137
155
 
138
156
  def resolve_path(path: Union[str, os.PathLike[str]]) -> str:
139
157
  if isinstance(path, str):
@@ -202,6 +220,12 @@ class StdFileSystem(FileSystem):
202
220
  def isdir(self, path: Union[str, os.PathLike[str]]) -> bool:
203
221
  return os.path.isdir(path)
204
222
 
223
+ def getctime(self, path: Union[str, os.PathLike[str]]) -> float:
224
+ return os.path.getctime(path)
225
+
226
+ def getmtime(self, path: Union[str, os.PathLike[str]]) -> float:
227
+ return os.path.getmtime(path)
228
+
205
229
  def mkdir(
206
230
  self, path: Union[str, os.PathLike[str]], mode: int = 0o777
207
231
  ) -> None:
@@ -231,6 +255,13 @@ class StdFileSystem(FileSystem):
231
255
  def rmdirs(self, path: Union[str, os.PathLike[str]]) -> None:
232
256
  os.removedirs(path)
233
257
 
258
+ def copy(
259
+ self,
260
+ oldpath: Union[str, os.PathLike[str]],
261
+ newpath: Union[str, os.PathLike[str]],
262
+ ) -> None:
263
+ shutil.copy(oldpath, newpath)
264
+
234
265
 
235
266
  #
236
267
  # Memory file system.
@@ -244,6 +275,9 @@ class MemoryFile(File):
244
275
  super().__init__()
245
276
  self._buffer = buffer
246
277
  self._pos = 0
278
+ now = datetime.datetime.now().timestamp()
279
+ self.ctime = now
280
+ self.mtime = now
247
281
 
248
282
  def read(self, size: Optional[int] = None) -> Union[str, bytes]:
249
283
  return self._buffer.read(size)
@@ -253,6 +287,7 @@ class MemoryFile(File):
253
287
 
254
288
  def write(self, content: Union[str, bytes]) -> None:
255
289
  self._buffer.write(content)
290
+ self.mtime = datetime.datetime.now().timestamp()
256
291
 
257
292
  def seek(self, offset: int, whence: Literal[0, 1, 2] = 0) -> int:
258
293
  return self._buffer.seek(offset, whence)
@@ -336,6 +371,24 @@ class MemoryFileSystem(FileSystem):
336
371
  def isdir(self, path: Union[str, os.PathLike[str]]) -> bool:
337
372
  return isinstance(self._locate(path), dict)
338
373
 
374
+ def getctime(self, path: Union[str, os.PathLike[str]]) -> float:
375
+ """Returns the creation time of a file."""
376
+ f = self._locate(path)
377
+ if isinstance(f, dict):
378
+ raise IsADirectoryError(path)
379
+ if f is None:
380
+ raise FileNotFoundError(path)
381
+ return f.ctime
382
+
383
+ def getmtime(self, path: Union[str, os.PathLike[str]]) -> float:
384
+ """Returns the last modification time of a file."""
385
+ f = self._locate(path)
386
+ if isinstance(f, dict):
387
+ raise IsADirectoryError(path)
388
+ if f is None:
389
+ raise FileNotFoundError(path)
390
+ return f.mtime
391
+
339
392
  def _parent_and_name(
340
393
  self, path: Union[str, os.PathLike[str]]
341
394
  ) -> tuple[dict[str, Any], str]:
@@ -460,6 +513,37 @@ class MemoryFileSystem(FileSystem):
460
513
  return not dir_dict
461
514
  _rmdir(self._root, self._internal_path(path))
462
515
 
516
+ def copy(
517
+ self,
518
+ oldpath: Union[str, os.PathLike[str]],
519
+ newpath: Union[str, os.PathLike[str]],
520
+ ) -> None:
521
+ old_file = self._locate(oldpath)
522
+ if old_file is None:
523
+ raise FileNotFoundError(oldpath)
524
+ if not isinstance(old_file, MemoryFile):
525
+ raise IsADirectoryError(oldpath)
526
+
527
+ if self.isdir(newpath):
528
+ _, old_file_name = self._parent_and_name(oldpath)
529
+ newpath = resolve_path(newpath)
530
+ newpath = newpath.rstrip('/') + '/' + old_file_name
531
+
532
+ # If newpath exists as file, remove it for overwrite.
533
+ if self.exists(newpath) and not self.isdir(newpath):
534
+ self.rm(newpath)
535
+ elif self.isdir(newpath):
536
+ raise IsADirectoryError(newpath)
537
+
538
+ old_pos = old_file.tell()
539
+ old_file.seek(0)
540
+ content = old_file.read()
541
+ old_file.seek(old_pos)
542
+
543
+ is_binary = isinstance(old_file._buffer, io.BytesIO) # pylint: disable=protected-access
544
+ with self.open(newpath, 'wb' if is_binary else 'w') as f_new:
545
+ f_new.write(content)
546
+
463
547
 
464
548
  class _FileSystemRegistry:
465
549
  """File system registry."""
@@ -567,6 +651,22 @@ class FsspecFileSystem(FileSystem):
567
651
  fs, path = fsspec.core.url_to_fs(path)
568
652
  return fs.isdir(path)
569
653
 
654
+ def getctime(self, path: Union[str, os.PathLike[str]]) -> float:
655
+ assert fsspec is not None, '`fsspec` is not installed.'
656
+ fs, path_in_fs = fsspec.core.url_to_fs(path)
657
+ created = fs.created(path_in_fs)
658
+ if created is None:
659
+ raise OSError(f'c-time is not available for path {path!r}')
660
+ return created.timestamp()
661
+
662
+ def getmtime(self, path: Union[str, os.PathLike[str]]) -> float:
663
+ assert fsspec is not None, '`fsspec` is not installed.'
664
+ fs, path_in_fs = fsspec.core.url_to_fs(path)
665
+ modified = fs.modified(path_in_fs)
666
+ if modified is None:
667
+ raise OSError(f'm-time is not available for path {path!r}')
668
+ return modified.timestamp()
669
+
570
670
  def mkdir(
571
671
  self,
572
672
  path: Union[str, os.PathLike[str]], mode: int = 0o777
@@ -615,6 +715,32 @@ class FsspecFileSystem(FileSystem):
615
715
  fs, path = fsspec.core.url_to_fs(path)
616
716
  fs.rm(path, recursive=True)
617
717
 
718
+ def copy(
719
+ self,
720
+ oldpath: Union[str, os.PathLike[str]],
721
+ newpath: Union[str, os.PathLike[str]],
722
+ ) -> None:
723
+ assert fsspec is not None, '`fsspec` is not installed.'
724
+ fs1, old_path_in_fs = fsspec.core.url_to_fs(oldpath)
725
+ fs2, new_path_in_fs = fsspec.core.url_to_fs(newpath)
726
+
727
+ if fs2.isdir(new_path_in_fs):
728
+ new_path_in_fs = os.path.join(
729
+ new_path_in_fs, os.path.basename(old_path_in_fs)
730
+ )
731
+
732
+ if fs1.__class__ == fs2.__class__:
733
+ fs1.copy(old_path_in_fs, new_path_in_fs)
734
+ else:
735
+ with fs1.open(old_path_in_fs, 'rb') as f1:
736
+ with fs2.open(new_path_in_fs, 'wb') as f2:
737
+ while True:
738
+ # Reads the file in 16MB chunks.
739
+ chunk = f1.read(16 * 1024 * 1024)
740
+ if not chunk:
741
+ break
742
+ f2.write(chunk)
743
+
618
744
 
619
745
  class _FsspecUriCatcher(FileSystem):
620
746
  """File system to catch URI paths and redirect to FsspecFileSystem."""
@@ -653,6 +779,12 @@ class _FsspecUriCatcher(FileSystem):
653
779
  def isdir(self, path: Union[str, os.PathLike[str]]) -> bool:
654
780
  return self.get_fs(path).isdir(path)
655
781
 
782
+ def getctime(self, path: Union[str, os.PathLike[str]]) -> float:
783
+ return self.get_fs(path).getctime(path)
784
+
785
+ def getmtime(self, path: Union[str, os.PathLike[str]]) -> float:
786
+ return self.get_fs(path).getmtime(path)
787
+
656
788
  def mkdir(
657
789
  self,
658
790
  path: Union[str, os.PathLike[str]],
@@ -684,6 +816,13 @@ class _FsspecUriCatcher(FileSystem):
684
816
  def rmdirs(self, path: Union[str, os.PathLike[str]]) -> None:
685
817
  self.get_fs(path).rmdirs(path)
686
818
 
819
+ def copy(
820
+ self,
821
+ oldpath: Union[str, os.PathLike[str]],
822
+ newpath: Union[str, os.PathLike[str]],
823
+ ) -> None:
824
+ self.get_fs(oldpath).copy(oldpath, newpath)
825
+
687
826
 
688
827
  if fsspec is not None:
689
828
  fsspec_fs = FsspecFileSystem()
@@ -751,6 +890,14 @@ def rm(path: Union[str, os.PathLike[str]]) -> None:
751
890
  _fs.get(path).rm(path)
752
891
 
753
892
 
893
+ def copy(
894
+ oldpath: Union[str, os.PathLike[str]],
895
+ newpath: Union[str, os.PathLike[str]],
896
+ ) -> None:
897
+ """Copies a file."""
898
+ _fs.get(oldpath).copy(oldpath, newpath)
899
+
900
+
754
901
  def path_exists(path: Union[str, os.PathLike[str]]) -> bool:
755
902
  """Returns True if path exists."""
756
903
  return _fs.get(path).exists(path)
@@ -776,6 +923,16 @@ def isdir(path: Union[str, os.PathLike[str]]) -> bool:
776
923
  return _fs.get(path).isdir(path)
777
924
 
778
925
 
926
+ def getctime(path: Union[str, os.PathLike[str]]) -> float:
927
+ """Returns the creation time of a file."""
928
+ return _fs.get(path).getctime(path)
929
+
930
+
931
+ def getmtime(path: Union[str, os.PathLike[str]]) -> float:
932
+ """Returns the last modification time of a file."""
933
+ return _fs.get(path).getmtime(path)
934
+
935
+
779
936
  def mkdir(path: Union[str, os.PathLike[str]], mode: int = 0o777) -> None:
780
937
  """Makes a directory."""
781
938
  _fs.get(path).mkdir(path, mode=mode)
@@ -12,9 +12,12 @@
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
19
22
  from unittest import mock
20
23
  import fsspec
@@ -153,6 +156,42 @@ class StdFileSystemTest(unittest.TestCase):
153
156
  os.path.join(tmp_dir, 'y')
154
157
  )
155
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
+
156
195
 
157
196
  class MemoryFileSystemTest(unittest.TestCase):
158
197
 
@@ -339,6 +378,57 @@ class MemoryFileSystemTest(unittest.TestCase):
339
378
  with self.assertRaises(FileNotFoundError):
340
379
  fs.rename('/mem/non-existent', '/mem/y')
341
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
+
342
432
 
343
433
  class FileIoApiTest(unittest.TestCase):
344
434
 
@@ -424,6 +514,19 @@ class FileIoApiTest(unittest.TestCase):
424
514
  sorted(file_system.glob('/mem/g/a/*')),
425
515
  ['/mem/g/a/b', '/mem/g/a/b/bar.txt', '/mem/g/a/foo2.txt'])
426
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
+
427
530
 
428
531
  class FsspecFileSystemTest(unittest.TestCase):
429
532
 
@@ -433,10 +536,12 @@ class FsspecFileSystemTest(unittest.TestCase):
433
536
  self.fs.pipe('memory:///a/b/c', b'abc')
434
537
  self.fs.pipe('memory:///a/b/d', b'abd')
435
538
  self.fs.mkdir('memory:///a/e')
539
+ self.tmp_dir = tempfile.mkdtemp()
436
540
 
437
541
  def tearDown(self):
438
542
  super().tearDown()
439
543
  fsspec.filesystem('memory').rm('/', recursive=True)
544
+ shutil.rmtree(self.tmp_dir)
440
545
 
441
546
  def test_read_file(self):
442
547
  self.assertEqual(file_system.readfile('memory:///a/b/c', mode='rb'), b'abc')
@@ -513,6 +618,44 @@ class FsspecFileSystemTest(unittest.TestCase):
513
618
  file_system.rmdirs('memory:///x')
514
619
  self.assertFalse(file_system.path_exists('memory:///x'))
515
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
+
516
659
  def test_fsspec_uri_catcher(self):
517
660
  with mock.patch.object(
518
661
  file_system.FsspecFileSystem, 'exists', return_value=True
@@ -539,6 +682,14 @@ class FsspecFileSystemTest(unittest.TestCase):
539
682
  'some-proto://foo', 'some-proto://bar'
540
683
  )
541
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
+
542
693
 
543
694
  if __name__ == '__main__':
544
695
  unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyglove
3
- Version: 0.5.0.dev202511300809
3
+ Version: 0.5.0.dev202601060812
4
4
  Summary: PyGlove: A library for manipulating Python objects.
5
5
  Home-page: https://github.com/google/pyglove
6
6
  Author: PyGlove Authors
@@ -56,8 +56,8 @@ pyglove/core/hyper/numerical_test.py,sha256=UWdH55Bok7bghYDLJOGsgOwV_2LNkhj1AmFw
56
56
  pyglove/core/hyper/object_template.py,sha256=YPALTV0mMULa7iuqnryTpA2wMsdyFZ_6g-R525asAr8,22222
57
57
  pyglove/core/hyper/object_template_test.py,sha256=TEFX7LIqUvdCdJILnK_gP5xIgNJKzRnioUF0CGVBzcY,9105
58
58
  pyglove/core/io/__init__.py,sha256=4ZT1a595DqQuLTNYc2JP_eCp_KesXvHmKRkr777bzpg,785
59
- pyglove/core/io/file_system.py,sha256=r7x_kDWDynKbAcO8tEkkRHShOPiYXyB9wmCXv2c-Oes,23149
60
- pyglove/core/io/file_system_test.py,sha256=QvcPEQj3hAk7xc8VkFda1ZzgsV0etBimc1V9CJXr_Rk,19145
59
+ pyglove/core/io/file_system.py,sha256=cggBMIzQxQpTjPsYQPQj8IsO-UpunsEGxaclYQcUHjw,28093
60
+ pyglove/core/io/file_system_test.py,sha256=2c2l3HCNS8Q4mv8k1dqopnGpeVLiWSzmc8eDIx4b5oo,24561
61
61
  pyglove/core/io/sequence.py,sha256=XdVpPBuvhUnrTIWMUrak_qdcNdUJBpjgH5c1b5I3E2A,8873
62
62
  pyglove/core/io/sequence_test.py,sha256=mnONyNG1M1sCae2tyI-tF8qns96htfZPKycthETPthU,4062
63
63
  pyglove/core/patching/__init__.py,sha256=C1Q1cWPV74YL3eXbzGvc-8aPw1DR8EK6lRhQYDCwHek,2059
@@ -220,8 +220,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
220
220
  pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
221
221
  pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
222
222
  pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
223
- pyglove-0.5.0.dev202511300809.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
224
- pyglove-0.5.0.dev202511300809.dist-info/METADATA,sha256=UenEruuR6yfx1_hUKjd-L5lbN15GMZnpOhKYeA7hwPc,7349
225
- pyglove-0.5.0.dev202511300809.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
226
- pyglove-0.5.0.dev202511300809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
227
- pyglove-0.5.0.dev202511300809.dist-info/RECORD,,
223
+ pyglove-0.5.0.dev202601060812.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
224
+ pyglove-0.5.0.dev202601060812.dist-info/METADATA,sha256=rS87VoQeUaln098UdoEdid_ZKVznt8kb7a8tPkcCubs,7349
225
+ pyglove-0.5.0.dev202601060812.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
226
+ pyglove-0.5.0.dev202601060812.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
227
+ pyglove-0.5.0.dev202601060812.dist-info/RECORD,,