Hide keyboard shortcuts

Hot-keys 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#!/usr/bin/env python 

2# cardinal_pythonlib/typing_helpers.py 

3 

4""" 

5=============================================================================== 

6 

7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com). 

8 

9 This file is part of cardinal_pythonlib. 

10 

11 Licensed under the Apache License, Version 2.0 (the "License"); 

12 you may not use this file except in compliance with the License. 

13 You may obtain a copy of the License at 

14 

15 https://www.apache.org/licenses/LICENSE-2.0 

16 

17 Unless required by applicable law or agreed to in writing, software 

18 distributed under the License is distributed on an "AS IS" BASIS, 

19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

20 See the License for the specific language governing permissions and 

21 limitations under the License. 

22 

23=============================================================================== 

24 

25**Unusual types for type hints.** 

26 

27""" 

28 

29from abc import abstractmethod 

30import csv 

31from typing import Any, Iterator, List, Optional, Sequence, Tuple, Type, Union 

32 

33 

34# ============================================================================= 

35# csv.writer 

36# ============================================================================= 

37 

38class CSVWriterType(object): 

39 """ 

40 Type hint for the result of ``csv.writer()`` 

41 

42 See https://stackoverflow.com/questions/51264355/how-to-type-annotate-object-returned-by-csv-writer 

43 """ # noqa 

44 

45 @abstractmethod 

46 def writerow(self, row: List[str]) -> None: 

47 pass 

48 

49 @abstractmethod 

50 def writerows(self, rows: List[List[str]]) -> None: 

51 pass 

52 

53 @property 

54 @abstractmethod 

55 def dialect(self) -> csv.Dialect: 

56 pass 

57 

58 

59# ============================================================================= 

60# Pep249DatabaseConnectionType 

61# ============================================================================= 

62 

63class Pep249DatabaseConnectionType(object): 

64 """ 

65 Type hint for a database connection compliant with PEP 249. See 

66 https://www.python.org/dev/peps/pep-0249/. 

67  

68 Not supported: 

69  

70 - https://www.python.org/dev/peps/pep-0249/#optional-error-handling-extensions 

71 - https://www.python.org/dev/peps/pep-0249/#optional-two-phase-commit-extensions 

72 """ # noqa 

73 

74 @abstractmethod 

75 def close(self) -> None: 

76 """ 

77 See https://www.python.org/dev/peps/pep-0249/#connection-objects 

78 """ 

79 pass 

80 

81 @abstractmethod 

82 def commit(self) -> None: 

83 """ 

84 See https://www.python.org/dev/peps/pep-0249/#connection-objects 

85 """ 

86 pass 

87 

88 @abstractmethod 

89 def rollback(self) -> None: 

90 """ 

91 See https://www.python.org/dev/peps/pep-0249/#connection-objects 

92 """ 

93 pass 

94 

95 @abstractmethod 

96 def cursor(self) -> "Pep249DatabaseCursorType": 

97 """ 

98 See https://www.python.org/dev/peps/pep-0249/#connection-objects 

99 """ 

100 pass 

101 

102 @property 

103 @abstractmethod 

104 def messages(self) -> List[Tuple[Type, Any]]: 

105 """ 

106 See 

107 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

108 """ 

109 pass 

110 

111 

112# ============================================================================= 

113# Pep249DatabaseConnectionType 

114# ============================================================================= 

115 

116_DATABASE_ROW_TYPE = Sequence[Any] 

117 

118 

119class Pep249DatabaseCursorType(object): 

120 """ 

121 Type hint for a database cursor compliant with PEP 249. See 

122 https://www.python.org/dev/peps/pep-0249/#cursor-objects 

123 

124 Example, as per https://docs.python.org/3.6/library/sqlite3.html: 

125 

126 .. code-block:: python 

127 

128 import sqlite3 

129 conn = sqlite3.connect(':memory:') 

130 c = conn.cursor() 

131 c.execute(''' 

132 CREATE TABLE stocks 

133 (date text, trans text, symbol text, qty real, price real) 

134 ''') 

135 c.execute(''' 

136 INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14) 

137 ''') 

138 conn.commit() 

139 

140 c.execute("SELECT * FROM stocks") 

141 print(repr(c.description)) 

142 

143 help(c) 

144 

145 See also: 

146 

147 - http://initd.org/psycopg/docs/cursor.html 

148 

149 """ 

150 

151 @abstractmethod 

152 def __init__(self, *args, **kwargs) -> None: 

153 pass 

154 

155 @abstractmethod 

156 def __iter__(self) -> Iterator[_DATABASE_ROW_TYPE]: 

157 """ 

158 See 

159 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

160 """ 

161 pass 

162 

163 @abstractmethod 

164 def __new__(cls, *args, **kwargs) -> "Pep249DatabaseCursorType": 

165 pass 

166 

167 @abstractmethod 

168 def __next__(self) -> None: 

169 pass 

170 

171 @property 

172 @abstractmethod 

173 def description(self) \ 

174 -> Optional[Sequence[Sequence[Any]]]: 

175 """ 

176 A sequence of column_description objects, where each column_description 

177 describes one result column and has the following items: 

178 

179 - name: ``str`` 

180 - type_code: ``Optional[Type]``? Not sure. 

181 - display_size: ``Optional[int]`` 

182 - internal_size: ``Optional[int]`` 

183 - precision: ``Optional[int]`` 

184 - scale: ``Optional[int]`` 

185 - null_ok: ``Optional[bool]`` 

186 

187 The attribute is ``None`` for operations that don't return rows, and 

188 for un-executed cursors. 

189 

190 """ 

191 pass 

192 

193 @property 

194 @abstractmethod 

195 def rowcount(self) -> int: 

196 """ 

197 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

198 """ 

199 pass 

200 

201 @abstractmethod 

202 def callproc(self, procname: str, *args, **kwargs) -> None: 

203 """ 

204 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

205 """ 

206 pass 

207 

208 @abstractmethod 

209 def close(self) -> None: 

210 """ 

211 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

212 """ 

213 pass 

214 

215 @abstractmethod 

216 def execute(self, operation: str, *args, **kwargs) -> None: 

217 """ 

218 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

219 """ 

220 pass 

221 

222 @abstractmethod 

223 def executemany(self, operation: str, *args, **kwargs) -> None: 

224 """ 

225 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

226 """ 

227 pass 

228 

229 @abstractmethod 

230 def fetchone(self) -> Optional[_DATABASE_ROW_TYPE]: 

231 """ 

232 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

233 """ 

234 pass 

235 

236 @abstractmethod 

237 def fetchmany(self, size: int = None) -> Sequence[_DATABASE_ROW_TYPE]: 

238 """ 

239 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

240 """ 

241 pass 

242 

243 @abstractmethod 

244 def fetchall(self) -> Sequence[_DATABASE_ROW_TYPE]: 

245 """ 

246 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

247 """ 

248 pass 

249 

250 @abstractmethod 

251 def nextset(self) -> Optional[bool]: 

252 """ 

253 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

254 """ 

255 pass 

256 

257 @property 

258 @abstractmethod 

259 def arraysize(self) -> int: 

260 """ 

261 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

262 """ 

263 # read/write attribute; see below 

264 pass 

265 

266 # noinspection PyUnresolvedReferences 

267 @arraysize.setter 

268 @abstractmethod 

269 def arraysize(self, val: int) -> None: 

270 """ 

271 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

272 """ 

273 # https://stackoverflow.com/questions/35344209/python-abstract-property-setter-with-concrete-getter 

274 pass 

275 

276 @abstractmethod 

277 def setinputsizes(self, sizes: Sequence[Union[Type, int]]) -> None: 

278 """ 

279 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

280 """ 

281 pass 

282 

283 @abstractmethod 

284 def setoutputsize(self, size: int, column: Optional[int]) -> None: 

285 """ 

286 See https://www.python.org/dev/peps/pep-0249/#cursor-objects 

287 """ 

288 pass 

289 

290 @property 

291 @abstractmethod 

292 def connection(self) -> Pep249DatabaseConnectionType: 

293 """ 

294 See 

295 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

296 """ 

297 pass 

298 

299 @property 

300 @abstractmethod 

301 def lastrowid(self) -> Optional[int]: 

302 """ 

303 See 

304 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

305 """ 

306 pass 

307 

308 @property 

309 @abstractmethod 

310 def rownumber(self) -> Optional[int]: 

311 """ 

312 See 

313 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

314 """ 

315 pass 

316 

317 @abstractmethod 

318 def scroll(self, value: int, mode: str = 'relative') -> None: 

319 """ 

320 See 

321 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

322 """ 

323 pass 

324 

325 @property 

326 @abstractmethod 

327 def messages(self) -> List[Tuple[Type, Any]]: 

328 """ 

329 See 

330 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

331 """ 

332 pass 

333 

334 @abstractmethod 

335 def next(self) -> _DATABASE_ROW_TYPE: 

336 """ 

337 See 

338 https://www.python.org/dev/peps/pep-0249/#optional-db-api-extensions 

339 """ 

340 pass