Source code for asyncutils.config

  1# ruff: noqa: BLE001,SIM115
  2from asyncutils._internal import log as l, patch as P, initialize as I
  3from asyncutils._internal.submodules import config_all as __all__
  4from asyncutils._internal.unparsed import N, c
  5import logging as L, sys as S
  6def __dir__(_=__all__): return _
[docs] 7class FaultyConfig(BaseException): 8 def __init__(self, k, w, c, /): self.key, self.wrong, self.correct = k, w, c; super().__init__(f'asyncutils: configuration for key {k!r} from AUTILSCFGPATH is faulty: expected {', '.join(c) if isinstance(c, tuple) else c.__name__}, got {w.__name__}')
9def f(e, _=__import__('_functools').partial(__import__, fromlist=('',)), f=frozenset(('thread', 'process', 'interpreter')), c='.', S=S): # noqa: B008,C901,PLR0911,PLR0912 # pragma: no cover 10 if not isinstance(e, str): raise TypeError('asyncutils: executor name should be a string') 11 d, c, w = e.rpartition(c) 12 if c: 13 try: return getattr(_(d), w) 14 except ImportError: ... 15 else: 16 d = 'loky' 17 if e in f: return getattr(_('concurrent.futures.'+e), e.title()+'PoolExecutor') 18 if e == 'dask': 19 try: return _('distributed.client').Client 20 except ImportError: d = 'dask.distributed' 21 elif e == 'deadpool': 22 try: return __import__(e).DeadPool 23 except ImportError: ... 24 elif e == 'loky_no_reuse': 25 try: return _('loky.process_executor').ProcessPoolExecutor 26 except ImportError: ... 27 elif e == d: 28 try: (r := _('loky.reusable_executor')._ReusablePoolExecutor).__new__ = lambda cls, *a, **k: cls.get_reusable_executor(*a, **k)[0]; return r 29 except ImportError: ... 30 elif e == 'ipython': return _('ipyparallel.client.view').ViewExecutor 31 else: 32 d, *a = e.split('_') 33 if d == 'elib': 34 try: a, e = a; return getattr(_('executorlib.executor.'+a), f'{a.title()}{e.title()}Executor') 35 except ImportError: d = 'executorlib' 36 elif d == 'pebble': 37 try: a = a[0]; return getattr(_('pebble.pool.'+a), a.title()+'Pool') 38 except ImportError: ... 39 else: raise FaultyConfig('executor', e, _('asyncutils.constants').POSSIBLE_EXECUTORS) 40 S.stderr.write(f'Error importing {d} (maybe not installed); falling back to ThreadPoolExecutor\n'); return _('concurrent.futures.thread').ThreadPoolExecutor 41def k(e, a=False, N=N): 42 if isinstance(x := N[e], str): 43 try: return int(x, 0) 44 except ValueError: 45 if a: raise FaultyConfig(e, x, int) 46 return x 47def g(e, a=False, t=(str, int, bytes), _=k): 48 if isinstance(x := _(e), str) and ((x.startswith("b'") and x.endswith("'")) or (x.startswith('b"') and x.endswith('"'))): 49 try: x = x.encode()[2:-1] # noqa: SIM105 50 except UnicodeEncodeError: ... 51 if isinstance(x, t) or (a and (x is None or isinstance(x, float))): return x 52 raise FaultyConfig(e, x, t) 53max_memory_errors, e, Executor, get_past_logs, m, M, o, s, _ = k('max_memory_errors'), g('seed', True), f(N.executor), str, 'a', False, __import__('os').name == 'posix', S.stderr, L.StreamHandler() 54silent, basic_repl, loaded_all, pdb = map(N.__getitem__, ('quiet', 'basic_repl', 'load_all', 'pdb')) 55match logging_to := g('log_to'): 56 case 'NULL': l.disabled = True 57 case 'MAKE': 58 T, m, h = 'asyncutils_log%d.log', 'x', 0 59 for h in range(1, 0x1001): 60 try: logging_to = (s := open(T%h, m)).name; break 61 except PermissionError as M: s.write(f'ERROR: insufficient permissions: {M}\n'); M = True; break 62 except AttributeError: raise SystemError("asyncutils: Python opened a file with no 'name' attribute when finding log file") from None 63 except Exception: ... 64 else: M = True 65 del T, h 66 case 'MEMORY': 67 from _io import StringIO as J 68 def get_past_logs(j=J, _=_): 69 if r := _.stream.getvalue(): _.setStream(j()) # ty: ignore[unresolved-attribute] 70 return r 71 get_past_logs.__text_signature__, s = '()', J(); del J # ty: ignore[unresolved-attribute] 72 case 'STDOUT': s = S.stdout 73 case 'STDERR': ... 74 case 1 if o: s, logging_to = S.stdout, 'STDOUT' 75 case 2 if o: logging_to = 'STDERR' 76 case str()|int()|bytes(): 77 try: M = True; logging_to = getattr(s := open(logging_to, m), 'name', logging_to); M = False 78 except PermissionError as b: s.write(f'ERROR: insufficient permissions: {b}\n') 79 except OSError as b: s.write(f'ERROR: {b}\n') 80 except Exception as b: s.write(f'ERROR: unexpected error opening log file: {b}\n') 81if M: s.write('ERROR: Failed to create log file; falling back to stderr\n') 82_.setStream(s) 83_.setFormatter(L.Formatter('%(asctime)s - asyncutils - %(levelname)s - %(message)s')) 84l.addHandler(_) 85(set_logger_level := lambda level, h=_, l=l: l.setLevel(level) or h.setLevel(level))(10*min(max(3-N.V+N.Q, 1), 5))
[docs] 86class Debugging: 87 __slots__ = 'orig_level', 'orig_name' 88 @property 89 def level(self, _=l): return _.level # noqa: PLR0206 90 @property 91 def entered(self): return self.orig_level is not None 92 def __init__(self): self.orig_level = self.orig_name = None
[docs] 93 def __enter__(self, _s=set_logger_level, _m=L._levelToName.__getitem__, _l=l, _d=10): 94 if self.entered: _l.warning('config.Debugging: context manager already entered') 95 else: 96 self.orig_name, self.orig_level = _m(l := _l.level), l; _s(_d) 97 if l != _d: _l.debug('config.Debugging: debug mode entered') 98 return self
[docs] 99 def __exit__(self, /, *_, _s=set_logger_level, _l=l, _L=10): 100 if not self.entered: return _l.warning('config.Debugging: context manager not entered') 101 if (l := self.orig_level) != _l.level == _L: _l.debug('config.Debugging: exiting debug mode'); _s(l) 102 else: _l.warning('config.Debugging: user already exited debug mode; original level was %s', self.orig_name) 103 self.orig_name = self.orig_level = None
104 def __repr__(self): return f'<asyncutils debug mode context manager (entered: {self.entered}) at {id(self):#x}>' 105 P.patch_method_signatures((__enter__, ''), (__exit__, P.exit_sig))
106debug, p = Debugging(), (A := I.A).pop 107I.p = d = l.debug # ty: ignore[invalid-assignment] 108if N.debug: 109 debug.__enter__(); d('python %s', S.version) # noqa: PLC2801 110 if silent: from asyncutils import __version__ as V; d(V.representation); d('platform: %s', S.platform) 111 if c: d('config file path: %s', c) 112while A: d(*p()) 113__import__('atexit').register(lambda s=s, _=d: None if s.closed else _('bye') or s.flush() or s.close()) 114def r(n, /): raise AttributeError(f"module 'asyncutils.config' has no attribute {n!r}") 115def __getattr__(n, /, _=e, r=r): 116 if n != '_randinst': r(n) 117 global _randinst; _randinst, __getattr__.__code__ = __import__('random').Random(_), r.__code__; return _randinst # ty: ignore[unresolved-global] 118P.patch_function_signatures((__getattr__, 'name, /'), (set_logger_level, 'level'), (__dir__, '')) 119if loaded_all: 120 i = I.Module.load 121 for _ in I.s.values(): i(_) # ty: ignore[invalid-argument-type] 122 d('all submodules loaded in %.2f milliseconds', __import__('asyncutils').time_since_boot()) 123del _, e, L, M, N, S, f, m, r, s, o, P, g, k, l, c, d, I