Coverage for python/lsst/resources/_resourceHandles/_baseResourceHandle.py: 64%

93 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 02:04 -0700

1# This file is part of lsst-resources. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11from __future__ import annotations 

12 

13from types import TracebackType 

14 

15__all__ = ("BaseResourceHandle", "CloseStatus", "ResourceHandleProtocol") 

16 

17from abc import ABC, abstractmethod, abstractproperty 

18from enum import Enum, auto 

19from io import SEEK_SET 

20from logging import Logger 

21from typing import AnyStr, Callable, Generic, Iterable, Optional, Protocol, Type, TypeVar, Union 

22 

23S = TypeVar("S", bound="ResourceHandleProtocol") 

24T = TypeVar("T", bound="BaseResourceHandle") 

25U = TypeVar("U", str, bytes) 

26 

27 

28class CloseStatus(Enum): 

29 """Enumerated closed/open status of a file handle, implementation detail 

30 that may be used by BaseResourceHandle children. 

31 """ 

32 

33 OPEN = auto() 

34 CLOSING = auto() 

35 CLOSED = auto() 

36 

37 

38class ResourceHandleProtocol(Protocol, Generic[U]): 

39 """Defines the interface protocol that is compatible with children of 

40 `BaseResourceHandle`. 

41 

42 Any class that satisfies this protocol can be used in any context where a 

43 `BaseResourceHandle` is expected. 

44 """ 

45 

46 @abstractproperty 

47 def mode(self) -> str: 

48 ... 

49 

50 @abstractmethod 

51 def close(self) -> None: 

52 ... 

53 

54 @abstractproperty 

55 def closed(self) -> bool: 

56 ... 

57 

58 @abstractmethod 

59 def fileno(self) -> int: 

60 ... 

61 

62 @abstractmethod 

63 def flush(self) -> None: 

64 ... 

65 

66 @abstractproperty 

67 def isatty(self) -> Union[bool, Callable[[], bool]]: 

68 ... 

69 

70 @abstractmethod 

71 def readable(self) -> bool: 

72 ... 

73 

74 @abstractmethod 

75 def readline(self, size: int = -1) -> U: 

76 ... 

77 

78 @abstractmethod 

79 def readlines(self, hint: int = -1) -> Iterable[U]: 

80 ... 

81 

82 @abstractmethod 

83 def seek(self, offset: int, whence: int = SEEK_SET, /) -> int: 

84 pass 

85 

86 @abstractmethod 

87 def seekable(self) -> bool: 

88 ... 

89 

90 @abstractmethod 

91 def tell(self) -> int: 

92 ... 

93 

94 @abstractmethod 

95 def truncate(self, size: Optional[int] = None) -> int: 

96 ... 

97 

98 @abstractmethod 

99 def writable(self) -> bool: 

100 ... 

101 

102 @abstractmethod 

103 def writelines(self, lines: Iterable[U], /) -> None: 

104 ... 

105 

106 @abstractmethod 

107 def read(self, size: int = -1) -> U: 

108 ... 

109 

110 @abstractmethod 

111 def write(self, b: U, /) -> int: 

112 ... 

113 

114 def __enter__(self: S) -> S: 

115 ... 

116 

117 def __exit__( 

118 self, 

119 exc_type: Optional[Type[BaseException]], 

120 exc_val: Optional[BaseException], 

121 exc_tb: Optional[TracebackType], 

122 /, 

123 ) -> Optional[bool]: 

124 ... 

125 

126 

127class BaseResourceHandle(ABC, ResourceHandleProtocol[U]): 

128 """Base class interface for the handle like interface of `ResourcePath` 

129 subclasses. 

130 

131 Parameters 

132 ---------- 

133 mode : `str` 

134 Handle modes as described in the python `io` module 

135 log : `~logging.Logger` 

136 Logger to used when writing messages 

137 newline : `str` 

138 When doing multiline operations, break the stream on given character 

139 Defaults to newline. 

140 

141 Notes 

142 ----- 

143 Documentation on the methods of this class line should refer to the 

144 corresponding methods in the `io` module. 

145 """ 

146 

147 _closed: CloseStatus 

148 _mode: str 

149 _log: Logger 

150 _newline: U 

151 

152 def __init__(self, mode: str, log: Logger, *, newline: Optional[AnyStr] = None) -> None: 

153 if newline is None: 

154 if "b" in mode: 

155 self._newline = b"\n" # type: ignore 

156 else: 

157 self._newline = "\n" # type: ignore 

158 else: 

159 self._newline = newline # type: ignore 

160 self._mode = mode 

161 self._log = log 

162 

163 @property 

164 def mode(self) -> str: 

165 return self._mode 

166 

167 def __enter__(self: T) -> T: 

168 self._closed = CloseStatus.OPEN 

169 return self 

170 

171 def __exit__( 

172 self, 

173 exc_type: Optional[Type[BaseException]], 

174 exc_bal: Optional[BaseException], 

175 exc_tb: Optional[TracebackType], 

176 ) -> Optional[bool]: 

177 self.close() 

178 return None