python-misc-utils 0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. py_misc_utils/__init__.py +0 -0
  2. py_misc_utils/abs_timeout.py +12 -0
  3. py_misc_utils/alog.py +311 -0
  4. py_misc_utils/app_main.py +179 -0
  5. py_misc_utils/archive_streamer.py +112 -0
  6. py_misc_utils/assert_checks.py +118 -0
  7. py_misc_utils/ast_utils.py +121 -0
  8. py_misc_utils/async_manager.py +189 -0
  9. py_misc_utils/break_control.py +63 -0
  10. py_misc_utils/buffered_iterator.py +35 -0
  11. py_misc_utils/cached_file.py +507 -0
  12. py_misc_utils/call_limiter.py +26 -0
  13. py_misc_utils/call_result_selector.py +13 -0
  14. py_misc_utils/cleanups.py +85 -0
  15. py_misc_utils/cmd.py +97 -0
  16. py_misc_utils/compression.py +116 -0
  17. py_misc_utils/cond_waiter.py +13 -0
  18. py_misc_utils/context_base.py +18 -0
  19. py_misc_utils/context_managers.py +67 -0
  20. py_misc_utils/core_utils.py +577 -0
  21. py_misc_utils/daemon_process.py +252 -0
  22. py_misc_utils/data_cache.py +46 -0
  23. py_misc_utils/date_utils.py +90 -0
  24. py_misc_utils/debug.py +24 -0
  25. py_misc_utils/dyn_modules.py +50 -0
  26. py_misc_utils/dynamod.py +103 -0
  27. py_misc_utils/env_config.py +35 -0
  28. py_misc_utils/executor.py +239 -0
  29. py_misc_utils/file_overwrite.py +29 -0
  30. py_misc_utils/fin_wrap.py +77 -0
  31. py_misc_utils/fp_utils.py +47 -0
  32. py_misc_utils/fs/__init__.py +0 -0
  33. py_misc_utils/fs/file_fs.py +127 -0
  34. py_misc_utils/fs/ftp_fs.py +242 -0
  35. py_misc_utils/fs/gcs_fs.py +196 -0
  36. py_misc_utils/fs/http_fs.py +241 -0
  37. py_misc_utils/fs/s3_fs.py +417 -0
  38. py_misc_utils/fs_base.py +133 -0
  39. py_misc_utils/fs_utils.py +207 -0
  40. py_misc_utils/gcs_fs.py +169 -0
  41. py_misc_utils/gen_indices.py +54 -0
  42. py_misc_utils/gfs.py +371 -0
  43. py_misc_utils/git_repo.py +77 -0
  44. py_misc_utils/global_namespace.py +110 -0
  45. py_misc_utils/http_async_fetcher.py +139 -0
  46. py_misc_utils/http_server.py +196 -0
  47. py_misc_utils/http_utils.py +143 -0
  48. py_misc_utils/img_utils.py +20 -0
  49. py_misc_utils/infix_op.py +20 -0
  50. py_misc_utils/inspect_utils.py +205 -0
  51. py_misc_utils/iostream.py +21 -0
  52. py_misc_utils/iter_file.py +117 -0
  53. py_misc_utils/key_wrap.py +46 -0
  54. py_misc_utils/lazy_import.py +25 -0
  55. py_misc_utils/lockfile.py +164 -0
  56. py_misc_utils/mem_size.py +64 -0
  57. py_misc_utils/mirror_from.py +72 -0
  58. py_misc_utils/mmap.py +16 -0
  59. py_misc_utils/module_utils.py +196 -0
  60. py_misc_utils/moving_average.py +19 -0
  61. py_misc_utils/msgpack_streamer.py +26 -0
  62. py_misc_utils/multi_wait.py +24 -0
  63. py_misc_utils/multiprocessing.py +102 -0
  64. py_misc_utils/named_array.py +224 -0
  65. py_misc_utils/no_break.py +46 -0
  66. py_misc_utils/no_except.py +32 -0
  67. py_misc_utils/np_ml_framework.py +184 -0
  68. py_misc_utils/np_utils.py +346 -0
  69. py_misc_utils/ntuple_utils.py +38 -0
  70. py_misc_utils/num_utils.py +54 -0
  71. py_misc_utils/obj.py +73 -0
  72. py_misc_utils/object_cache.py +100 -0
  73. py_misc_utils/object_tracker.py +88 -0
  74. py_misc_utils/ordered_set.py +71 -0
  75. py_misc_utils/osfd.py +27 -0
  76. py_misc_utils/packet.py +22 -0
  77. py_misc_utils/parquet_streamer.py +69 -0
  78. py_misc_utils/pd_utils.py +254 -0
  79. py_misc_utils/periodic_task.py +61 -0
  80. py_misc_utils/pickle_wrap.py +121 -0
  81. py_misc_utils/pipeline.py +98 -0
  82. py_misc_utils/remap_pickle.py +50 -0
  83. py_misc_utils/resource_manager.py +155 -0
  84. py_misc_utils/rnd_utils.py +56 -0
  85. py_misc_utils/run_once.py +19 -0
  86. py_misc_utils/scheduler.py +135 -0
  87. py_misc_utils/select_params.py +300 -0
  88. py_misc_utils/signal.py +141 -0
  89. py_misc_utils/skl_utils.py +270 -0
  90. py_misc_utils/split.py +147 -0
  91. py_misc_utils/state.py +53 -0
  92. py_misc_utils/std_module.py +56 -0
  93. py_misc_utils/stream_dataframe.py +176 -0
  94. py_misc_utils/streamed_file.py +144 -0
  95. py_misc_utils/tempdir.py +79 -0
  96. py_misc_utils/template_replace.py +51 -0
  97. py_misc_utils/tensor_stream.py +269 -0
  98. py_misc_utils/thread_context.py +33 -0
  99. py_misc_utils/throttle.py +30 -0
  100. py_misc_utils/time_trigger.py +18 -0
  101. py_misc_utils/timegen.py +11 -0
  102. py_misc_utils/traceback.py +49 -0
  103. py_misc_utils/tracking_executor.py +91 -0
  104. py_misc_utils/transform_array.py +42 -0
  105. py_misc_utils/uncompress.py +35 -0
  106. py_misc_utils/url_fetcher.py +157 -0
  107. py_misc_utils/utils.py +538 -0
  108. py_misc_utils/varint.py +50 -0
  109. py_misc_utils/virt_array.py +52 -0
  110. py_misc_utils/weak_call.py +33 -0
  111. py_misc_utils/work_results.py +100 -0
  112. py_misc_utils/writeback_file.py +43 -0
  113. python_misc_utils-0.2.dist-info/METADATA +36 -0
  114. python_misc_utils-0.2.dist-info/RECORD +117 -0
  115. python_misc_utils-0.2.dist-info/WHEEL +5 -0
  116. python_misc_utils-0.2.dist-info/licenses/LICENSE +13 -0
  117. python_misc_utils-0.2.dist-info/top_level.txt +1 -0
py_misc_utils/cmd.py ADDED
@@ -0,0 +1,97 @@
1
+ import functools
2
+ import os
3
+ import shlex
4
+ import signal
5
+ import string
6
+ import subprocess
7
+ import sys
8
+
9
+ from . import alog
10
+ from . import fs_utils as fsu
11
+ from . import signal as sgn
12
+ from . import template_replace as tr
13
+
14
+
15
+ class _SigHandler:
16
+
17
+ def __init__(self, proc, logfd=None):
18
+ self._proc = proc
19
+ self._logfd = logfd
20
+ self._sent = set()
21
+
22
+ def __call__(self, sig, frame):
23
+ if sig not in self._sent:
24
+ self._sent.add(sig)
25
+ alog.async_log(alog.WARNING,
26
+ f'{signal.strsignal(sig)} received. Forwarding it to running ' \
27
+ f'child {self._proc.pid} ...',
28
+ file=self._logfd)
29
+
30
+ self._proc.send_signal(sig)
31
+
32
+ return sgn.HANDLED
33
+
34
+
35
+ class _Writer:
36
+
37
+ def __init__(self, fd):
38
+ self.fd = fd
39
+ self._is_binary = fsu.is_binary(fd)
40
+
41
+ def write(self, data):
42
+ if self._is_binary:
43
+ if isinstance(data, str):
44
+ data = data.encode()
45
+ elif not isinstance(data, str):
46
+ data = data.decode()
47
+
48
+ self.fd.write(data)
49
+ self.fd.flush()
50
+
51
+
52
+ class _Reader:
53
+
54
+ def __init__(self, fd):
55
+ self._read = getattr(fd, 'read1', None)
56
+ if self._read is None:
57
+ self._read = getattr(fd, 'readline', None)
58
+
59
+ def read(self):
60
+ return self._read()
61
+
62
+
63
+ def _lookup(tmpl_envs, key, defval=None):
64
+ for env in tmpl_envs:
65
+ value = env.get(key)
66
+ if value is not None:
67
+ return value
68
+
69
+ alog.xraise(KeyError, f'Unable to lookup "{key}" while substituting command ' \
70
+ f'line arguments')
71
+
72
+
73
+ def run(cmd, outfd=None, tmpl_envs=None, **kwargs):
74
+ if isinstance(cmd, str):
75
+ tmpl_envs = tmpl_envs or (os.environ,)
76
+ cmd = tr.template_replace(cmd, lookup_fn=functools.partial(_lookup, tmpl_envs))
77
+ cmd = shlex.split(cmd)
78
+
79
+ alog.debug(f'Running: {cmd}')
80
+
81
+ proc = subprocess.Popen(cmd,
82
+ stdout=subprocess.PIPE,
83
+ stderr=subprocess.STDOUT,
84
+ **kwargs)
85
+
86
+ reader = _Reader(proc.stdout)
87
+ writer = _Writer(outfd or sys.stdout)
88
+ with sgn.Signals('INT, TERM', _SigHandler(proc, logfd=writer.fd)):
89
+ while True:
90
+ data = reader.read()
91
+ if data:
92
+ writer.write(data)
93
+ elif proc.poll() is not None:
94
+ break
95
+
96
+ return proc.returncode
97
+
@@ -0,0 +1,116 @@
1
+ import bz2
2
+ import collections
3
+ import gzip
4
+ import contextlib
5
+ import lzma
6
+ import os
7
+ import shutil
8
+
9
+ from . import gfs
10
+
11
+
12
+ def fgzip(src, dest):
13
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
14
+ with gzip.open(outfd, mode='wb') as zfd:
15
+ shutil.copyfileobj(infd, zfd)
16
+
17
+
18
+ def fgunzip(src, dest):
19
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
20
+ with gzip.open(infd, mode='rb') as zfd:
21
+ shutil.copyfileobj(zfd, outfd)
22
+
23
+
24
+ def fbzip2(src, dest):
25
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
26
+ with bz2.open(outfd, mode='wb') as zfd:
27
+ shutil.copyfileobj(infd, zfd)
28
+
29
+
30
+ def fbunzip2(src, dest):
31
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
32
+ with bz2.open(infd, mode='rb') as zfd:
33
+ shutil.copyfileobj(zfd, outfd)
34
+
35
+
36
+ def fxzip(src, dest):
37
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
38
+ with lzma.open(outfd, mode='wb') as zfd:
39
+ shutil.copyfileobj(infd, zfd)
40
+
41
+
42
+ def fxunzip(src, dest):
43
+ with gfs.open(src, mode='rb') as infd, gfs.open(dest, mode='wb') as outfd:
44
+ with lzma.open(infd, mode='rb') as zfd:
45
+ shutil.copyfileobj(zfd, outfd)
46
+
47
+
48
+ _Processor = collections.namedtuple('Processor', 'processor, module')
49
+
50
+ _COMPRESSORS = {
51
+ '.bz2': _Processor(processor=fbzip2, module=bz2),
52
+ '.bzip': _Processor(processor=fbzip2, module=bz2),
53
+ '.gz': _Processor(processor=fgzip, module=gzip),
54
+ '.xz': _Processor(processor=fxzip, module=lzma),
55
+ }
56
+
57
+ def compressor(ext):
58
+ return _COMPRESSORS.get(ext)
59
+
60
+
61
+ _DECOMPRESSORS = {
62
+ '.bz2': _Processor(processor=fbunzip2, module=bz2),
63
+ '.bzip': _Processor(processor=fbunzip2, module=bz2),
64
+ '.gz': _Processor(processor=fgunzip, module=gzip),
65
+ '.xz': _Processor(processor=fxunzip, module=lzma),
66
+ }
67
+
68
+ def decompressor(ext):
69
+ return _DECOMPRESSORS.get(ext)
70
+
71
+
72
+ def compress(src, dest):
73
+ _, ext = os.path.splitext(dest)
74
+ comp = compressor(ext)
75
+ if comp is not None:
76
+ comp.processor(src, dest)
77
+ else:
78
+ shutil.copyfile(src, dest)
79
+
80
+
81
+ def decompress(src, dest):
82
+ _, ext = os.path.splitext(src)
83
+ decomp = decompressor(ext)
84
+ if decomp is not None:
85
+ decomp.processor(src, dest)
86
+ else:
87
+ shutil.copyfile(src, dest)
88
+
89
+
90
+ @contextlib.contextmanager
91
+ def dopen(path, mode='r', **kwargs):
92
+ _, ext = os.path.splitext(path)
93
+
94
+ decomp = decompressor(ext)
95
+ if decomp is None:
96
+ with gfs.open(path, mode=mode, **kwargs) as fd:
97
+ yield fd
98
+ else:
99
+ with gfs.open(path, mode='rb', **kwargs) as fd:
100
+ with decomp.module.open(fd, mode=mode) as zfd:
101
+ yield zfd
102
+
103
+
104
+ @contextlib.contextmanager
105
+ def copen(path, mode='w', **kwargs):
106
+ _, ext = os.path.splitext(path)
107
+
108
+ comp = compressor(ext)
109
+ if comp is None:
110
+ with gfs.open(path, mode=mode, **kwargs) as fd:
111
+ yield fd
112
+ else:
113
+ with gfs.open(path, mode='wb', **kwargs) as fd:
114
+ with comp.module.open(fd, mode=mode) as zfd:
115
+ yield zfd
116
+
@@ -0,0 +1,13 @@
1
+ from . import abs_timeout as abst
2
+ from . import timegen as tg
3
+
4
+
5
+ class CondWaiter:
6
+
7
+ def __init__(self, timeout=None, timegen=None):
8
+ self._timegen = tg.TimeGen() if timegen is None else timegen
9
+ self._timeo = abst.AbsTimeout(timeout, timefn=self._timegen.now)
10
+
11
+ def wait(self, cond):
12
+ return self._timegen.wait(cond, timeout=self._timeo.get())
13
+
@@ -0,0 +1,18 @@
1
+ from . import utils as ut
2
+
3
+
4
+ class ContextBase:
5
+
6
+ def __init__(self, default_ctx):
7
+ self._ctx = ut.make_object(**default_ctx)
8
+
9
+ def _new_ctx(self, **kwargs):
10
+ ctx = self._ctx
11
+ args = ctx.__dict__.copy()
12
+ args.update(**kwargs)
13
+
14
+ nctx = ut.make_object(**args)
15
+ self._ctx = nctx
16
+
17
+ return nctx
18
+
@@ -0,0 +1,67 @@
1
+ import contextlib
2
+
3
+
4
+ class CtxManager:
5
+
6
+ def __init__(self, infn, outfn):
7
+ self._infn = infn
8
+ self._outfn = outfn
9
+
10
+ def __enter__(self):
11
+ return self._infn()
12
+
13
+ def __exit__(self, *exc):
14
+ return self._outfn(*exc)
15
+
16
+
17
+ class Wrapper:
18
+
19
+ def __init__(self, v, attr=None, finfn=None):
20
+ self.v = v
21
+ self._finfn = finfn or getattr(v, attr or 'close')
22
+
23
+ def __enter__(self):
24
+ return self
25
+
26
+ def detach(self):
27
+ self._finfn = None
28
+
29
+ return self.v
30
+
31
+ def __exit__(self, *exc):
32
+ if self._finfn is not None:
33
+ self._finfn()
34
+
35
+ return False
36
+
37
+
38
+ class Pack(contextlib.ExitStack):
39
+
40
+ def __init__(self, *wrap_ctxs, wrap_obj=None, wrap_idx=None):
41
+ super().__init__()
42
+ self._wrap_ctxs = wrap_ctxs
43
+ self._wrap_obj = wrap_obj
44
+ self._wrap_idx = wrap_idx
45
+
46
+ def __enter__(self):
47
+ super().__enter__()
48
+
49
+ try:
50
+ wres = [self.enter_context(ctx) for ctx in self._wrap_ctxs]
51
+ except:
52
+ self.close()
53
+ raise
54
+
55
+ if self._wrap_obj is not None:
56
+ return self._wrap_obj
57
+
58
+ return wres[-1] if self._wrap_idx is None else wres[self._wrap_idx]
59
+
60
+
61
+ def detach(obj):
62
+ return obj.detach() if isinstance(obj, CtxManagerProxy) else obj
63
+
64
+
65
+ def cond(value, ctxfn, *args, **kwargs):
66
+ return ctxfn(*args, **kwargs) if value else contextlib.nullcontext()
67
+