Coverage for python/lsst/daf/butler/core/_butlerUri/utils.py: 40%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22from __future__ import annotations
24import contextlib
25import posixpath
26import logging
27import os
29from pathlib import Path, PurePath, PurePosixPath
31__all__ = ('os2posix', 'posix2os', 'NoTransaction')
33from typing import (
34 Any,
35 Callable,
36 Iterator,
37 Union,
38)
40# Determine if the path separator for the OS looks like POSIX
41IS_POSIX = os.sep == posixpath.sep
43# Root path for this operating system. This can use getcwd which
44# can fail in some situations so in the default case assume that
45# posix means posix and only determine explicitly in the non-posix case.
46if IS_POSIX: 46 ↛ 49line 46 didn't jump to line 49, because the condition on line 46 was never false
47 OS_ROOT_PATH = posixpath.sep
48else:
49 OS_ROOT_PATH = Path().resolve().root
51log = logging.getLogger(__name__)
54def os2posix(ospath: str) -> str:
55 """Convert a local path description to a POSIX path description.
57 Parameters
58 ----------
59 ospath : `str`
60 Path using the local path separator.
62 Returns
63 -------
64 posix : `str`
65 Path using POSIX path separator
66 """
67 if IS_POSIX:
68 return ospath
70 posix = PurePath(ospath).as_posix()
72 # PurePath strips trailing "/" from paths such that you can no
73 # longer tell if a path is meant to be referring to a directory
74 # Try to fix this.
75 if ospath.endswith(os.sep) and not posix.endswith(posixpath.sep):
76 posix += posixpath.sep
78 return posix
81def posix2os(posix: Union[PurePath, str]) -> str:
82 """Convert a POSIX path description to a local path description.
84 Parameters
85 ----------
86 posix : `str`, `PurePath`
87 Path using the POSIX path separator.
89 Returns
90 -------
91 ospath : `str`
92 Path using OS path separator
93 """
94 if IS_POSIX:
95 return str(posix)
97 posixPath = PurePosixPath(posix)
98 paths = list(posixPath.parts)
100 # Have to convert the root directory after splitting
101 if paths[0] == posixPath.root:
102 paths[0] = OS_ROOT_PATH
104 # Trailing "/" is stripped so we need to add back an empty path
105 # for consistency
106 if str(posix).endswith(posixpath.sep):
107 paths.append("")
109 return os.path.join(*paths)
112class NoTransaction:
113 """A simple emulation of the `DatastoreTransaction` class.
115 Notes
116 -----
117 Does nothing. Used as a fallback in the absence of an explicit transaction
118 class.
119 """
121 def __init__(self) -> None: # noqa: D107
122 return
124 @contextlib.contextmanager
125 def undoWith(self, name: str, undoFunc: Callable, *args: Any, **kwargs: Any) -> Iterator[None]:
126 """No-op context manager to replace `DatastoreTransaction`."""
127 yield None