pyglove 0.4.5.dev202503190809__py3-none-any.whl → 0.4.5.dev202503210809__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.
@@ -76,6 +76,10 @@ class FileSystem(metaclass=abc.ABCMeta):
76
76
  ) -> File:
77
77
  """Opens a file with a path."""
78
78
 
79
+ @abc.abstractmethod
80
+ def chmod(self, path: Union[str, os.PathLike[str]], mode: int) -> None:
81
+ """Changes the permission of a file."""
82
+
79
83
  @abc.abstractmethod
80
84
  def exists(self, path: Union[str, os.PathLike[str]]) -> bool:
81
85
  """Returns True if a path exists."""
@@ -167,6 +171,9 @@ class StdFileSystem(FileSystem):
167
171
  ) -> File:
168
172
  return StdFile(io.open(path, mode, **kwargs))
169
173
 
174
+ def chmod(self, path: Union[str, os.PathLike[str]], mode: int) -> None:
175
+ os.chmod(path, mode)
176
+
170
177
  def exists(self, path: Union[str, os.PathLike[str]]) -> bool:
171
178
  return os.path.exists(path)
172
179
 
@@ -272,6 +279,10 @@ class MemoryFileSystem(FileSystem):
272
279
  raise FileNotFoundError(path)
273
280
  return file
274
281
 
282
+ def chmod(self, path: Union[str, os.PathLike[str]], mode: int) -> None:
283
+ # No-op.
284
+ del path, mode
285
+
275
286
  def exists(self, path: Union[str, os.PathLike[str]]) -> bool:
276
287
  return self._locate(path) is not None
277
288
 
@@ -411,6 +422,11 @@ def open(path: Union[str, os.PathLike[str]], mode: str = 'r', **kwargs) -> File:
411
422
  return _fs.get(path).open(path, mode, **kwargs)
412
423
 
413
424
 
425
+ def chmod(path: Union[str, os.PathLike[str]], mode: int) -> None:
426
+ """Changes the permission of a file."""
427
+ _fs.get(path).chmod(path, mode)
428
+
429
+
414
430
  def readfile(
415
431
  path: Union[str, os.PathLike[str]],
416
432
  mode: str = 'r',
@@ -432,11 +448,14 @@ def writefile(
432
448
  content: Union[str, bytes],
433
449
  *,
434
450
  mode: str = 'w',
451
+ perms: Optional[int] = 0o664, # Default to world-readable.
435
452
  **kwargs,
436
453
  ) -> None:
437
454
  """Writes content to a file."""
438
455
  with _fs.get(path).open(path, mode=mode, **kwargs) as f:
439
456
  f.write(content)
457
+ if perms is not None:
458
+ chmod(path, perms)
440
459
 
441
460
 
442
461
  def rm(path: Union[str, os.PathLike[str]]) -> None:
@@ -26,9 +26,11 @@ class Sequence(metaclass=abc.ABCMeta):
26
26
 
27
27
  def __init__(
28
28
  self,
29
+ perms: Optional[int] = None,
29
30
  serializer: Optional[Callable[[Any], Union[bytes, str]]] = None,
30
31
  deserializer: Optional[Callable[[Union[bytes, str]], Any]] = None
31
32
  ):
33
+ self._perms = perms
32
34
  self._serializer = serializer
33
35
  self._deserializer = deserializer
34
36
 
@@ -88,6 +90,7 @@ class SequenceIO(metaclass=abc.ABCMeta):
88
90
  path: Union[str, os.PathLike[str]],
89
91
  mode: str,
90
92
  *,
93
+ perms: Optional[int],
91
94
  serializer: Optional[Callable[[Any], Union[bytes, str]]],
92
95
  deserializer: Optional[Callable[[Union[bytes, str]], Any]],
93
96
  **kwargs
@@ -130,6 +133,7 @@ def open_sequence(
130
133
  path: Union[str, os.PathLike[str]],
131
134
  mode: str = 'r',
132
135
  *,
136
+ perms: Optional[int] = 0o664, # Default to world-readable.
133
137
  serializer: Optional[
134
138
  Callable[[Any], Union[bytes, str]]
135
139
  ] = None,
@@ -143,6 +147,7 @@ def open_sequence(
143
147
  Args:
144
148
  path: The path to the sequence.
145
149
  mode: The mode of the sequence.
150
+ perms: (Optional) The permissions of the sequence.
146
151
  serializer: (Optional) A serializer function for converting a structured
147
152
  object to a string or bytes.
148
153
  deserializer: (Optional) A deserializer function for converting a string or
@@ -158,7 +163,7 @@ def open_sequence(
158
163
  if make_dirs_if_not_exist:
159
164
  file_system.mkdirs(parent_dir, exist_ok=True)
160
165
  return _registry.get(path).open(
161
- path, mode, serializer=serializer, deserializer=deserializer
166
+ path, mode, perms=perms, serializer=serializer, deserializer=deserializer
162
167
  )
163
168
 
164
169
 
@@ -170,10 +175,12 @@ class MemorySequence(Sequence):
170
175
  path: str,
171
176
  mode: str,
172
177
  records: list[Union[str, bytes]],
178
+ *,
179
+ perms: Optional[int],
173
180
  serializer: Optional[Callable[[Any], Union[bytes, str]]],
174
181
  deserializer: Optional[Callable[[Union[bytes, str]], Any]]
175
182
  ):
176
- super().__init__(serializer, deserializer)
183
+ super().__init__(perms, serializer, deserializer)
177
184
  self._path = path
178
185
  self._mode = mode
179
186
  self._records = records
@@ -226,6 +233,7 @@ class MemorySequenceIO(SequenceIO):
226
233
  path: Union[str, os.PathLike[str]],
227
234
  mode: str,
228
235
  *,
236
+ perms: Optional[int],
229
237
  serializer: Optional[Callable[[Any], Union[bytes, str]]],
230
238
  deserializer: Optional[Callable[[Union[bytes, str]], Any]],
231
239
  **kwargs
@@ -236,7 +244,7 @@ class MemorySequenceIO(SequenceIO):
236
244
  self._root[path] = []
237
245
  return MemorySequence(
238
246
  path, mode, self._root[path],
239
- serializer=serializer, deserializer=deserializer
247
+ perms=perms, serializer=serializer, deserializer=deserializer
240
248
  )
241
249
 
242
250
 
@@ -248,12 +256,16 @@ class LineSequence(Sequence):
248
256
 
249
257
  def __init__(
250
258
  self,
251
- file: file_system.File,
259
+ path: str,
260
+ mode: str,
261
+ perms: Optional[int],
252
262
  serializer: Optional[Callable[[Any], Union[bytes, str]]],
253
263
  deserializer: Optional[Callable[[Union[bytes, str]], Any]],
254
264
  ) -> None:
255
- super().__init__(serializer, deserializer)
256
- self._file = file
265
+ super().__init__(perms, serializer, deserializer)
266
+ self._path = path
267
+ self._mode = mode
268
+ self._file = file_system.open(path, mode)
257
269
 
258
270
  def __len__(self):
259
271
  raise NotImplementedError(
@@ -277,6 +289,8 @@ class LineSequence(Sequence):
277
289
 
278
290
  def close(self) -> None:
279
291
  self._file.close()
292
+ if ('w' in self._mode or 'a' in self._mode) and self._perms is not None:
293
+ file_system.chmod(self._path, self._perms)
280
294
 
281
295
 
282
296
  class LineSequenceIO(SequenceIO):
@@ -287,13 +301,12 @@ class LineSequenceIO(SequenceIO):
287
301
  path: Union[str, os.PathLike[str]],
288
302
  mode: str,
289
303
  *,
304
+ perms: Optional[int],
290
305
  serializer: Optional[Callable[[Any], Union[bytes, str]]],
291
306
  deserializer: Optional[Callable[[Union[bytes, str]], Any]],
292
307
  **kwargs
293
308
  ) -> Sequence:
294
309
  """Opens a reader for a sequence."""
295
310
  del kwargs
296
- return LineSequence(
297
- file_system.open(path, mode), serializer, deserializer
298
- )
311
+ return LineSequence(path, mode, perms, serializer, deserializer)
299
312
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pyglove
3
- Version: 0.4.5.dev202503190809
3
+ Version: 0.4.5.dev202503210809
4
4
  Summary: PyGlove: A library for manipulating Python objects.
5
5
  Home-page: https://github.com/google/pyglove
6
6
  Author: PyGlove Authors
@@ -31,6 +31,7 @@ Dynamic: description-content-type
31
31
  Dynamic: home-page
32
32
  Dynamic: keywords
33
33
  Dynamic: license
34
+ Dynamic: license-file
34
35
  Dynamic: requires-dist
35
36
  Dynamic: summary
36
37
 
@@ -54,9 +54,9 @@ pyglove/core/hyper/numerical_test.py,sha256=UWdH55Bok7bghYDLJOGsgOwV_2LNkhj1AmFw
54
54
  pyglove/core/hyper/object_template.py,sha256=YPALTV0mMULa7iuqnryTpA2wMsdyFZ_6g-R525asAr8,22222
55
55
  pyglove/core/hyper/object_template_test.py,sha256=TEFX7LIqUvdCdJILnK_gP5xIgNJKzRnioUF0CGVBzcY,9105
56
56
  pyglove/core/io/__init__.py,sha256=4ZT1a595DqQuLTNYc2JP_eCp_KesXvHmKRkr777bzpg,785
57
- pyglove/core/io/file_system.py,sha256=CKb8wpXnoH9VHhY5LzOkUakSdBF3gshLkGxNZBUoZNM,13386
57
+ pyglove/core/io/file_system.py,sha256=E_kSi1Lqo31al4GJYywCzJT97X3ByW8Te4xVfAM93D4,13990
58
58
  pyglove/core/io/file_system_test.py,sha256=quJ74i7uEw7aaNIW6steIvn5VKrei5qOLJuOa4Og64w,8692
59
- pyglove/core/io/sequence.py,sha256=7QWMGXPtJzHyGPgqkT3yJ01FxKJ4mP4lF5HRDiIHNbQ,8165
59
+ pyglove/core/io/sequence.py,sha256=eRxv_LVdsEVgJARiEhDj8m2KNJ2FhPSafW7V00w49OM,8705
60
60
  pyglove/core/io/sequence_test.py,sha256=6tmnS7frBuDR8ussT5jugeh23TDsPDrDnbfxHh81Gy4,3891
61
61
  pyglove/core/patching/__init__.py,sha256=C1Q1cWPV74YL3eXbzGvc-8aPw1DR8EK6lRhQYDCwHek,2059
62
62
  pyglove/core/patching/object_factory.py,sha256=fsiqFET9LWQV4xZXJrPFu3j5IRovSi_zrJba7KiYGZ0,3368
@@ -212,8 +212,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
212
212
  pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
213
213
  pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
214
214
  pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
215
- pyglove-0.4.5.dev202503190809.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
216
- pyglove-0.4.5.dev202503190809.dist-info/METADATA,sha256=Ey-JJUgcPxknulbx7rcPNJKfKABWPz7tNhckxQJ_8Z8,7067
217
- pyglove-0.4.5.dev202503190809.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
218
- pyglove-0.4.5.dev202503190809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
219
- pyglove-0.4.5.dev202503190809.dist-info/RECORD,,
215
+ pyglove-0.4.5.dev202503210809.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
216
+ pyglove-0.4.5.dev202503210809.dist-info/METADATA,sha256=AGVau_jM2FIr1llnGuNfRwZItvKf97UG3WQ05XfhIGg,7089
217
+ pyglove-0.4.5.dev202503210809.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
218
+ pyglove-0.4.5.dev202503210809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
219
+ pyglove-0.4.5.dev202503210809.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.1.0)
2
+ Generator: setuptools (77.0.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5