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

1from typing import Any, Callable, Dict, List, Optional, Union 

2 

3from itertools import dropwhile, takewhile 

4from pathlib import Path 

5import inspect 

6import logging 

7import os 

8 

9import wrapt 

10 

11LOG_LEVEL = os.environ.get('LOG_LEVEL', 'WARNING').upper() 

12logging.basicConfig(level=LOG_LEVEL) 

13LOGGER = logging.getLogger(__name__) 

14# ------------------------------------------------------------------------------ 

15 

16''' 

17Imports only python builtins and contains only function for use within or 

18outside of Docker environment (ie no dependencies or specific python versions.) 

19''' 

20 

21 

22def relative_path(module, path): 

23 # type: (Union[str, Path], Union[str, Path]) -> Path 

24 ''' 

25 Resolve path given current module's file path and given suffix. 

26 

27 Args: 

28 module (str or Path): Always __file__ of current module. 

29 path (str or Path): Path relative to __file__. 

30 

31 Returns: 

32 Path: Resolved Path object. 

33 ''' 

34 module_root = Path(module).parent 

35 path_ = Path(path).parts # type: Any 

36 path_ = list(dropwhile(lambda x: x == ".", path_)) 

37 up = len(list(takewhile(lambda x: x == "..", path_))) 

38 path_ = Path(*path_[up:]) 

39 root = list(module_root.parents)[up - 1] 

40 output = Path(root, path_).absolute() 

41 

42 LOGGER.debug( 

43 f'relative_path called with: {module} and {path_}. Returned: {output}') 

44 return output 

45 

46 

47def get_function_signature(function): 

48 # type: (Callable) -> Dict 

49 ''' 

50 Inspect a given function and return its arguments as a list and its keyword 

51 arguments as a dict. 

52 

53 Args: 

54 function (function): Function to be inspected. 

55 

56 Returns: 

57 dict: args and kwargs. 

58 ''' 

59 spec = inspect.getfullargspec(function) 

60 args = list(spec.args) 

61 kwargs = {} # type: Any 

62 if spec.defaults is not None: 

63 args = args[:-len(spec.defaults)] 

64 kwargs = list(spec.args)[-len(spec.defaults):] 

65 kwargs = dict(zip(kwargs, spec.defaults)) 

66 return dict(args=args, kwargs=kwargs) 

67 

68 

69def api_function(wrapped=None, **kwargs): 

70 # type: (Optional[Callable], **Any) -> Callable 

71 ''' 

72 A decorator that enforces keyword argument only function signatures and 

73 required keyword argument values when called. 

74 

75 Args: 

76 wrapped (function): For dev use. Default: None. 

77 \*\*kwargs (dict): Keyword arguments. # noqa: W605 

78 

79 Raises: 

80 TypeError: If non-keyword argument found in functionn signature. 

81 ValueError: If keyword arg with value of '<required>' is found. 

82 

83 Returns: 

84 api function. 

85 ''' 

86 @wrapt.decorator 

87 def wrapper(wrapped, instance, args, kwargs): 

88 sig = get_function_signature(wrapped) 

89 

90 # ensure no arguments are present 

91 if len(sig['args']) > 0: 

92 msg = 'Function may only have keyword arguments. ' 

93 msg += f"Found non-keyword arguments: {sig['args']}." 

94 raise TypeError(msg) 

95 

96 # ensure all required kwarg values are present 

97 params = sig['kwargs'] 

98 params.update(kwargs) 

99 for key, val in params.items(): 

100 if val == '<required>': 

101 msg = f'Missing required keyword argument: {key}.' 

102 raise ValueError(msg) 

103 

104 LOGGER.debug(f'{wrapped} called with {params}.') 

105 return wrapped(*args, **kwargs) 

106 return wrapper(wrapped) 

107 

108 

109def is_standard_module(name): 

110 # type: (str) -> bool 

111 ''' 

112 Determines if given module name is a python builtin. 

113 

114 Args: 

115 name (str): Python module name. 

116 

117 Returns: 

118 bool: Whether string names a python module. 

119 ''' 

120 return name in _PYTHON_STANDARD_MODULES 

121 

122 

123_PYTHON_STANDARD_MODULES = [ 

124 '__future__', 

125 '__main__', 

126 '_dummy_thread', 

127 '_thread', 

128 'abc', 

129 'aifc', 

130 'argparse', 

131 'array', 

132 'ast', 

133 'asynchat', 

134 'asyncio', 

135 'asyncore', 

136 'atexit', 

137 'audioop', 

138 'base64', 

139 'bdb', 

140 'binascii', 

141 'binhex', 

142 'bisect', 

143 'builtins', 

144 'bz2', 

145 'calendar', 

146 'cgi', 

147 'cgitb', 

148 'chunk', 

149 'cmath', 

150 'cmd', 

151 'code', 

152 'codecs', 

153 'codeop', 

154 'collections', 

155 'collections.abc', 

156 'colorsys', 

157 'compileall', 

158 'concurrent', 

159 'concurrent.futures', 

160 'configparser', 

161 'contextlib', 

162 'contextvars', 

163 'copy', 

164 'copyreg', 

165 'cProfile', 

166 'crypt', 

167 'csv', 

168 'ctypes', 

169 'curses', 

170 'curses.ascii', 

171 'curses.panel', 

172 'curses.textpad', 

173 'dataclasses', 

174 'datetime', 

175 'dbm', 

176 'dbm.dumb', 

177 'dbm.gnu', 

178 'dbm.ndbm', 

179 'decimal', 

180 'difflib', 

181 'dis', 

182 'distutils', 

183 'distutils.archive_util', 

184 'distutils.bcppcompiler', 

185 'distutils.ccompiler', 

186 'distutils.cmd', 

187 'distutils.command', 

188 'distutils.command.bdist', 

189 'distutils.command.bdist_dumb', 

190 'distutils.command.bdist_msi', 

191 'distutils.command.bdist_packager', 

192 'distutils.command.bdist_rpm', 

193 'distutils.command.bdist_wininst', 

194 'distutils.command.build', 

195 'distutils.command.build_clib', 

196 'distutils.command.build_ext', 

197 'distutils.command.build_py', 

198 'distutils.command.build_scripts', 

199 'distutils.command.check', 

200 'distutils.command.clean', 

201 'distutils.command.config', 

202 'distutils.command.install', 

203 'distutils.command.install_data', 

204 'distutils.command.install_headers', 

205 'distutils.command.install_lib', 

206 'distutils.command.install_scripts', 

207 'distutils.command.register', 

208 'distutils.command.sdist', 

209 'distutils.core', 

210 'distutils.cygwinccompiler', 

211 'distutils.debug', 

212 'distutils.dep_util', 

213 'distutils.dir_util', 

214 'distutils.dist', 

215 'distutils.errors', 

216 'distutils.extension', 

217 'distutils.fancy_getopt', 

218 'distutils.file_util', 

219 'distutils.filelist', 

220 'distutils.log', 

221 'distutils.msvccompiler', 

222 'distutils.spawn', 

223 'distutils.sysconfig', 

224 'distutils.text_file', 

225 'distutils.unixccompiler', 

226 'distutils.util', 

227 'distutils.version', 

228 'doctest', 

229 'dummy_threading', 

230 'email', 

231 'email.charset', 

232 'email.contentmanager', 

233 'email.encoders', 

234 'email.errors', 

235 'email.generator', 

236 'email.header', 

237 'email.headerregistry', 

238 'email.iterators', 

239 'email.message', 

240 'email.mime', 

241 'email.parser', 

242 'email.policy', 

243 'email.utils', 

244 'encodings', 

245 'encodings.idna', 

246 'encodings.mbcs', 

247 'encodings.utf_8_sig', 

248 'ensurepip', 

249 'enum', 

250 'errno', 

251 'faulthandler', 

252 'fcntl', 

253 'filecmp', 

254 'fileinput', 

255 'fnmatch', 

256 'formatter', 

257 'fractions', 

258 'ftplib', 

259 'functools', 

260 'gc', 

261 'getopt', 

262 'getpass', 

263 'gettext', 

264 'glob', 

265 'grp', 

266 'gzip', 

267 'hashlib', 

268 'heapq', 

269 'hmac', 

270 'html', 

271 'html.entities', 

272 'html.parser', 

273 'http', 

274 'http.client', 

275 'http.cookiejar', 

276 'http.cookies', 

277 'http.server', 

278 'imaplib', 

279 'imghdr', 

280 'imp', 

281 'importlib', 

282 'importlib.abc', 

283 'importlib.machinery', 

284 'importlib.resources', 

285 'importlib.util', 

286 'inspect', 

287 'io', 

288 'ipaddress', 

289 'itertools', 

290 'json', 

291 'json.tool', 

292 'keyword', 

293 'lib2to3', 

294 'linecache', 

295 'locale', 

296 'logging', 

297 'logging.config', 

298 'logging.handlers', 

299 'lzma', 

300 'macpath', 

301 'mailbox', 

302 'mailcap', 

303 'marshal', 

304 'math', 

305 'mimetypes', 

306 'mmap', 

307 'modulefinder', 

308 'msilib', 

309 'msvcrt', 

310 'multiprocessing', 

311 'multiprocessing.connection', 

312 'multiprocessing.dummy', 

313 'multiprocessing.managers', 

314 'multiprocessing.pool', 

315 'multiprocessing.sharedctypes', 

316 'netrc', 

317 'nis', 

318 'nntplib', 

319 'numbers', 

320 'operator', 

321 'optparse', 

322 'os', 

323 'os.path', 

324 'ossaudiodev', 

325 'parser', 

326 'pathlib', 

327 'pdb', 

328 'pickle', 

329 'pickletools', 

330 'pipes', 

331 'pkgutil', 

332 'platform', 

333 'plistlib', 

334 'poplib', 

335 'posix', 

336 'pprint', 

337 'profile', 

338 'pstats', 

339 'pty', 

340 'pwd', 

341 'py_compile', 

342 'pyclbr', 

343 'pydoc', 

344 'queue', 

345 'quopri', 

346 'random', 

347 're', 

348 'readline', 

349 'reprlib', 

350 'resource', 

351 'rlcompleter', 

352 'runpy', 

353 'sched', 

354 'secrets', 

355 'select', 

356 'selectors', 

357 'shelve', 

358 'shlex', 

359 'shutil', 

360 'signal', 

361 'site', 

362 'smtpd', 

363 'smtplib', 

364 'sndhdr', 

365 'socket', 

366 'socketserver', 

367 'spwd', 

368 'sqlite3', 

369 'ssl', 

370 'stat', 

371 'statistics', 

372 'string', 

373 'stringprep', 

374 'struct', 

375 'subprocess', 

376 'sunau', 

377 'symbol', 

378 'symtable', 

379 'sys', 

380 'sysconfig', 

381 'syslog', 

382 'tabnanny', 

383 'tarfile', 

384 'telnetlib', 

385 'tempfile', 

386 'termios', 

387 'test', 

388 'test.support', 

389 'test.support.script_helper', 

390 'textwrap', 

391 'threading', 

392 'time', 

393 'timeit', 

394 'tkinter', 

395 'tkinter.scrolledtext', 

396 'tkinter.tix', 

397 'tkinter.ttk', 

398 'token', 

399 'tokenize', 

400 'trace', 

401 'traceback', 

402 'tracemalloc', 

403 'tty', 

404 'turtle', 

405 'turtledemo', 

406 'types', 

407 'typing', 

408 'unicodedata', 

409 'unittest', 

410 'unittest.mock', 

411 'urllib', 

412 'urllib.error', 

413 'urllib.parse', 

414 'urllib.request', 

415 'urllib.response', 

416 'urllib.robotparser', 

417 'uu', 

418 'uuid', 

419 'venv', 

420 'warnings', 

421 'wave', 

422 'weakref', 

423 'webbrowser', 

424 'winreg', 

425 'winsound', 

426 'wsgiref', 

427 'wsgiref.handlers', 

428 'wsgiref.headers', 

429 'wsgiref.simple_server', 

430 'wsgiref.util', 

431 'wsgiref.validate', 

432 'xdrlib', 

433 'xml', 

434 'xml.dom', 

435 'xml.dom.minidom', 

436 'xml.dom.pulldom', 

437 'xml.etree.ElementTree', 

438 'xml.parsers.expat', 

439 'xml.parsers.expat.errors', 

440 'xml.parsers.expat.model', 

441 'xml.sax', 

442 'xml.sax.handler', 

443 'xml.sax.saxutils', 

444 'xml.sax.xmlreader', 

445 'xmlrpc', 

446 'xmlrpc.client', 

447 'xmlrpc.server', 

448 'zipapp', 

449 'zipfile', 

450 'zipimport', 

451 'zlib' 

452] # type: List[str]