lsst-resources 29.2025.2500__tar.gz → 29.2025.2700__tar.gz

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.
Files changed (53) hide show
  1. {lsst_resources-29.2025.2500/python/lsst_resources.egg-info → lsst_resources-29.2025.2700}/PKG-INFO +1 -1
  2. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/file.py +33 -9
  3. lsst_resources-29.2025.2700/python/lsst/resources/version.py +2 -0
  4. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700/python/lsst_resources.egg-info}/PKG-INFO +1 -1
  5. lsst_resources-29.2025.2500/python/lsst/resources/version.py +0 -2
  6. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/COPYRIGHT +0 -0
  7. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/LICENSE +0 -0
  8. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/MANIFEST.in +0 -0
  9. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/README.md +0 -0
  10. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/doc/lsst.resources/CHANGES.rst +0 -0
  11. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/doc/lsst.resources/dav.rst +0 -0
  12. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/doc/lsst.resources/index.rst +0 -0
  13. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/doc/lsst.resources/internal-api.rst +0 -0
  14. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/doc/lsst.resources/s3.rst +0 -0
  15. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/pyproject.toml +0 -0
  16. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/__init__.py +0 -0
  17. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/__init__.py +0 -0
  18. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/__init__.py +0 -0
  19. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/_baseResourceHandle.py +0 -0
  20. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/_davResourceHandle.py +0 -0
  21. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/_fileResourceHandle.py +0 -0
  22. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/_httpResourceHandle.py +0 -0
  23. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourceHandles/_s3ResourceHandle.py +0 -0
  24. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/_resourcePath.py +0 -0
  25. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/dav.py +0 -0
  26. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/davutils.py +0 -0
  27. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/gs.py +0 -0
  28. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/http.py +0 -0
  29. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/location.py +0 -0
  30. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/mem.py +0 -0
  31. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/packageresource.py +0 -0
  32. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/py.typed +0 -0
  33. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/s3.py +0 -0
  34. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/s3utils.py +0 -0
  35. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/schemeless.py +0 -0
  36. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/tests.py +0 -0
  37. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst/resources/utils.py +0 -0
  38. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst_resources.egg-info/SOURCES.txt +0 -0
  39. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst_resources.egg-info/dependency_links.txt +0 -0
  40. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst_resources.egg-info/requires.txt +0 -0
  41. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst_resources.egg-info/top_level.txt +0 -0
  42. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/python/lsst_resources.egg-info/zip-safe +0 -0
  43. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/setup.cfg +0 -0
  44. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_dav.py +0 -0
  45. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_file.py +0 -0
  46. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_gs.py +0 -0
  47. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_http.py +0 -0
  48. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_location.py +0 -0
  49. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_mem.py +0 -0
  50. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_resource.py +0 -0
  51. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_s3.py +0 -0
  52. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_s3utils.py +0 -0
  53. {lsst_resources-29.2025.2500 → lsst_resources-29.2025.2700}/tests/test_schemeless.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-resources
3
- Version: 29.2025.2500
3
+ Version: 29.2025.2700
4
4
  Summary: An abstraction layer for reading and writing from URI file resources.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -21,6 +21,7 @@ import os.path
21
21
  import posixpath
22
22
  import re
23
23
  import shutil
24
+ import stat
24
25
  import urllib.parse
25
26
  from collections.abc import Iterator
26
27
  from typing import IO, TYPE_CHECKING
@@ -328,15 +329,38 @@ class FileResourcePath(ResourcePath):
328
329
  # the same output directory. This at least guarantees that
329
330
  # if multiple processes are writing to the same file
330
331
  # simultaneously the file we end up with will not be corrupt.
331
- with self.temporary_uri(prefix=self.parent(), suffix=self.getExtension()) as temp_copy:
332
- shutil.copy(local_src, temp_copy.ospath)
333
- with transaction.undoWith(f"copy from {local_src}", os.remove, newFullPath):
334
- # os.rename works even if the file exists.
335
- # It's possible that another process has copied a file
336
- # in whilst this one was copying. If overwrite
337
- # protection is needed then another stat() call should
338
- # happen here.
339
- os.rename(temp_copy.ospath, newFullPath)
332
+ if overwrite:
333
+ with self.temporary_uri(prefix=self.parent(), suffix=self.getExtension()) as temp_copy:
334
+ shutil.copy(local_src, temp_copy.ospath)
335
+ with transaction.undoWith(f"copy from {local_src}", os.remove, newFullPath):
336
+ os.rename(temp_copy.ospath, newFullPath)
337
+ else:
338
+ # Create the file exclusively to ensure that no others are
339
+ # trying to write.
340
+ temp_path = newFullPath + ".transfer-tmp"
341
+ try:
342
+ with open(temp_path, "x"):
343
+ pass
344
+ except FileExistsError:
345
+ raise FileExistsError(
346
+ f"Another process is writing to '{self}'."
347
+ f" Transfer from {src} cannot be completed."
348
+ )
349
+ with transaction.undoWith(f"copy from {local_src}", os.remove, temp_path):
350
+ # Make sure file is writable, no matter the umask.
351
+ st = os.stat(temp_path)
352
+ os.chmod(temp_path, st.st_mode | stat.S_IWUSR)
353
+ shutil.copy(local_src, temp_path)
354
+ # Use link/remove to atomically and exclusively move the
355
+ # file into place (only one concurrent linker can win).
356
+ try:
357
+ os.link(temp_path, newFullPath)
358
+ except FileExistsError:
359
+ raise FileExistsError(
360
+ f"Another process wrote to '{self}'. Transfer from {src} cannot be completed."
361
+ )
362
+ finally:
363
+ os.remove(temp_path)
340
364
  elif transfer == "link":
341
365
  # Try hard link and if that fails use a symlink
342
366
  with transaction.undoWith(f"link to {local_src}", os.remove, newFullPath):
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "29.2025.2700"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-resources
3
- Version: 29.2025.2500
3
+ Version: 29.2025.2700
4
4
  Summary: An abstraction layer for reading and writing from URI file resources.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -1,2 +0,0 @@
1
- __all__ = ["__version__"]
2
- __version__ = "29.2025.2500"