omlish 0.0.0.dev470__py3-none-any.whl → 0.0.0.dev472__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.
- omlish/__about__.py +2 -2
 - omlish/inject/__init__.py +4 -0
 - omlish/inject/elements.py +17 -0
 - omlish/inject/impl/elements.py +17 -2
 - omlish/inject/impl/injector.py +17 -19
 - omlish/inject/impl/maysync.py +3 -4
 - omlish/inject/impl/sync.py +3 -4
 - omlish/inject/injector.py +31 -2
 - omlish/inject/maysync.py +2 -4
 - omlish/inject/sync.py +5 -4
 - omlish/lang/imports/proxy.py +10 -1
 - omlish/lite/abstract.py +54 -24
 - omlish/lite/dataclasses.py +14 -0
 - omlish/term/pager.py +235 -0
 - omlish/term/terminfo.py +935 -0
 - omlish/term/termstate.py +67 -0
 - omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/METADATA +1 -1
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/RECORD +24 -21
 - /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/WHEEL +0 -0
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/entry_points.txt +0 -0
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/licenses/LICENSE +0 -0
 - {omlish-0.0.0.dev470.dist-info → omlish-0.0.0.dev472.dist-info}/top_level.txt +0 -0
 
    
        omlish/term/pager.py
    ADDED
    
    | 
         @@ -0,0 +1,235 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ruff: noqa: S602 S605
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            #   Copyright 2000-2008 Michael Hudson-Doyle <micahel@gmail.com>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #                       Armin Rigo
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            #                   All Rights Reserved
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted
         
     | 
| 
      
 10 
     | 
    
         
            +
            # without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and
         
     | 
| 
      
 11 
     | 
    
         
            +
            # this permission notice appear in supporting documentation.
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
         
     | 
| 
      
 14 
     | 
    
         
            +
            # MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
         
     | 
| 
      
 15 
     | 
    
         
            +
            # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
         
     | 
| 
      
 17 
     | 
    
         
            +
            #
         
     | 
| 
      
 18 
     | 
    
         
            +
            # https://github.com/python/cpython/tree/bcced02604f845b2b71d0a1dd95f95366bd7774d/Lib/_pyrepl
         
     | 
| 
      
 19 
     | 
    
         
            +
            import io
         
     | 
| 
      
 20 
     | 
    
         
            +
            import os
         
     | 
| 
      
 21 
     | 
    
         
            +
            import re
         
     | 
| 
      
 22 
     | 
    
         
            +
            import subprocess
         
     | 
| 
      
 23 
     | 
    
         
            +
            import sys
         
     | 
| 
      
 24 
     | 
    
         
            +
            import tempfile
         
     | 
| 
      
 25 
     | 
    
         
            +
            import termios
         
     | 
| 
      
 26 
     | 
    
         
            +
            import tty
         
     | 
| 
      
 27 
     | 
    
         
            +
            import typing as ta
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            from .. import check
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            ##
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            class Pager(ta.Protocol):
         
     | 
| 
      
 36 
     | 
    
         
            +
                def __call__(self, text: str, title: str = '') -> None:
         
     | 
| 
      
 37 
     | 
    
         
            +
                    ...
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            def get_pager() -> Pager:
         
     | 
| 
      
 41 
     | 
    
         
            +
                """Decide what method to use for paging through text."""
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                if not hasattr(sys.stdin, 'isatty'):
         
     | 
| 
      
 44 
     | 
    
         
            +
                    return plain_pager
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                if not hasattr(sys.stdout, 'isatty'):
         
     | 
| 
      
 47 
     | 
    
         
            +
                    return plain_pager
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                if not sys.stdin.isatty() or not sys.stdout.isatty():
         
     | 
| 
      
 50 
     | 
    
         
            +
                    return plain_pager
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                if sys.platform == 'emscripten':
         
     | 
| 
      
 53 
     | 
    
         
            +
                    return plain_pager
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
         
     | 
| 
      
 56 
     | 
    
         
            +
                if use_pager:
         
     | 
| 
      
 57 
     | 
    
         
            +
                    if sys.platform == 'win32':  # pipes completely broken in Windows
         
     | 
| 
      
 58 
     | 
    
         
            +
                        raise OSError
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    elif os.environ.get('TERM') in ('dumb', 'emacs'):
         
     | 
| 
      
 61 
     | 
    
         
            +
                        return lambda text, title='': pipe_pager(plain(text), use_pager, title)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 64 
     | 
    
         
            +
                        return lambda text, title='': pipe_pager(text, use_pager, title)
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                if os.environ.get('TERM') in ('dumb', 'emacs'):
         
     | 
| 
      
 67 
     | 
    
         
            +
                    return plain_pager
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                if sys.platform == 'win32':
         
     | 
| 
      
 70 
     | 
    
         
            +
                    return lambda text, title='': tempfile_pager(plain(text), 'more <')
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                if hasattr(os, 'system') and os.system('(pager) 2>/dev/null') == 0:
         
     | 
| 
      
 73 
     | 
    
         
            +
                    return lambda text, title='': pipe_pager(text, 'pager', title)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
         
     | 
| 
      
 76 
     | 
    
         
            +
                    return lambda text, title='': pipe_pager(text, 'less', title)
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                import tempfile
         
     | 
| 
      
 79 
     | 
    
         
            +
                (fd, filename) = tempfile.mkstemp()
         
     | 
| 
      
 80 
     | 
    
         
            +
                os.close(fd)
         
     | 
| 
      
 81 
     | 
    
         
            +
                try:
         
     | 
| 
      
 82 
     | 
    
         
            +
                    if hasattr(os, 'system') and os.system(f'more "{filename}"') == 0:
         
     | 
| 
      
 83 
     | 
    
         
            +
                        return lambda text, title='': pipe_pager(text, 'more', title)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 86 
     | 
    
         
            +
                        return tty_pager
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                finally:
         
     | 
| 
      
 89 
     | 
    
         
            +
                    os.unlink(filename)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            def escape_stdout(text: str) -> str:
         
     | 
| 
      
 93 
     | 
    
         
            +
                # Escape non-encodable characters to avoid encoding errors later
         
     | 
| 
      
 94 
     | 
    
         
            +
                encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
         
     | 
| 
      
 95 
     | 
    
         
            +
                return text.encode(encoding, 'backslashreplace').decode(encoding)
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            def escape_less(s: str) -> str:
         
     | 
| 
      
 99 
     | 
    
         
            +
                return re.sub(r'([?:.%\\])', r'\\\1', s)
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            def plain(text: str) -> str:
         
     | 
| 
      
 103 
     | 
    
         
            +
                """Remove boldface formatting from text."""
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                return re.sub('.\b', '', text)
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            def tty_pager(text: str, title: str = '') -> None:
         
     | 
| 
      
 109 
     | 
    
         
            +
                """Page through text on a text terminal."""
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                lines = plain(escape_stdout(text)).split('\n')
         
     | 
| 
      
 112 
     | 
    
         
            +
                has_tty = False
         
     | 
| 
      
 113 
     | 
    
         
            +
                try:
         
     | 
| 
      
 114 
     | 
    
         
            +
                    fd = sys.stdin.fileno()
         
     | 
| 
      
 115 
     | 
    
         
            +
                    old = termios.tcgetattr(fd)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    tty.setcbreak(fd)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    has_tty = True
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                    def getchar() -> str:
         
     | 
| 
      
 120 
     | 
    
         
            +
                        return sys.stdin.read(1)
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                except (ImportError, AttributeError, io.UnsupportedOperation):
         
     | 
| 
      
 123 
     | 
    
         
            +
                    def getchar() -> str:
         
     | 
| 
      
 124 
     | 
    
         
            +
                        return sys.stdin.readline()[:-1][:1]
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                try:
         
     | 
| 
      
 127 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 128 
     | 
    
         
            +
                        h = int(os.environ.get('LINES', '0'))
         
     | 
| 
      
 129 
     | 
    
         
            +
                    except ValueError:
         
     | 
| 
      
 130 
     | 
    
         
            +
                        h = 0
         
     | 
| 
      
 131 
     | 
    
         
            +
                    if h <= 1:
         
     | 
| 
      
 132 
     | 
    
         
            +
                        h = 25
         
     | 
| 
      
 133 
     | 
    
         
            +
                    r = inc = h - 1
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                    sys.stdout.write('\n'.join(lines[:inc]) + '\n')
         
     | 
| 
      
 136 
     | 
    
         
            +
                    while lines[r:]:
         
     | 
| 
      
 137 
     | 
    
         
            +
                        sys.stdout.write('-- more --')
         
     | 
| 
      
 138 
     | 
    
         
            +
                        sys.stdout.flush()
         
     | 
| 
      
 139 
     | 
    
         
            +
                        c = getchar()
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                        if c in ('q', 'Q'):
         
     | 
| 
      
 142 
     | 
    
         
            +
                            sys.stdout.write('\r          \r')
         
     | 
| 
      
 143 
     | 
    
         
            +
                            break
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                        elif c in ('\r', '\n'):
         
     | 
| 
      
 146 
     | 
    
         
            +
                            sys.stdout.write('\r          \r' + lines[r] + '\n')
         
     | 
| 
      
 147 
     | 
    
         
            +
                            r = r + 1
         
     | 
| 
      
 148 
     | 
    
         
            +
                            continue
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                        if c in ('b', 'B', '\x1b'):
         
     | 
| 
      
 151 
     | 
    
         
            +
                            r = r - inc - inc
         
     | 
| 
      
 152 
     | 
    
         
            +
                            if r < 0:
         
     | 
| 
      
 153 
     | 
    
         
            +
                                r = 0
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                        sys.stdout.write('\n' + '\n'.join(lines[r:r + inc]) + '\n')
         
     | 
| 
      
 156 
     | 
    
         
            +
                        r = r + inc
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                finally:
         
     | 
| 
      
 159 
     | 
    
         
            +
                    if has_tty:
         
     | 
| 
      
 160 
     | 
    
         
            +
                        termios.tcsetattr(fd, termios.TCSAFLUSH, old)  # noqa
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            def plain_pager(text: str, title: str = '') -> None:
         
     | 
| 
      
 164 
     | 
    
         
            +
                """Simply print unformatted text. This is the ultimate fallback."""
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                sys.stdout.write(plain(escape_stdout(text)))
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
            def pipe_pager(text: str, cmd: str, title: str = '') -> None:
         
     | 
| 
      
 170 
     | 
    
         
            +
                """Page through text by feeding it to another program."""
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                env = os.environ.copy()
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                if title:
         
     | 
| 
      
 175 
     | 
    
         
            +
                    title += ' '
         
     | 
| 
      
 176 
     | 
    
         
            +
                esc_title = escape_less(title)
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                prompt_string = (
         
     | 
| 
      
 179 
     | 
    
         
            +
                    f' {esc_title}'
         
     | 
| 
      
 180 
     | 
    
         
            +
                    '?ltline %lt?L/%L.'
         
     | 
| 
      
 181 
     | 
    
         
            +
                    ':byte %bB?s/%s.'
         
     | 
| 
      
 182 
     | 
    
         
            +
                    '.'
         
     | 
| 
      
 183 
     | 
    
         
            +
                    '?e (END):?pB %pB\\%..'
         
     | 
| 
      
 184 
     | 
    
         
            +
                    ' (press h for help or q to quit)'
         
     | 
| 
      
 185 
     | 
    
         
            +
                )
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                env['LESS'] = f'-RmPm{prompt_string}$PM{prompt_string}$'
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                proc = subprocess.Popen(
         
     | 
| 
      
 190 
     | 
    
         
            +
                    cmd,
         
     | 
| 
      
 191 
     | 
    
         
            +
                    shell=True,
         
     | 
| 
      
 192 
     | 
    
         
            +
                    stdin=subprocess.PIPE,
         
     | 
| 
      
 193 
     | 
    
         
            +
                    errors='backslashreplace',
         
     | 
| 
      
 194 
     | 
    
         
            +
                    env=env,
         
     | 
| 
      
 195 
     | 
    
         
            +
                )
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                try:
         
     | 
| 
      
 198 
     | 
    
         
            +
                    with check.not_none(proc.stdin) as pipe:
         
     | 
| 
      
 199 
     | 
    
         
            +
                        try:
         
     | 
| 
      
 200 
     | 
    
         
            +
                            pipe.write(text)
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                        except KeyboardInterrupt:
         
     | 
| 
      
 203 
     | 
    
         
            +
                            # We've hereby abandoned whatever text hasn't been written, but the pager is still in control of the
         
     | 
| 
      
 204 
     | 
    
         
            +
                            # terminal.
         
     | 
| 
      
 205 
     | 
    
         
            +
                            pass
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                except OSError:
         
     | 
| 
      
 208 
     | 
    
         
            +
                    pass  # Ignore broken pipes caused by quitting the pager program.
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                while True:
         
     | 
| 
      
 211 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 212 
     | 
    
         
            +
                        proc.wait()
         
     | 
| 
      
 213 
     | 
    
         
            +
                        break
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                    except KeyboardInterrupt:
         
     | 
| 
      
 216 
     | 
    
         
            +
                        # Ignore ctl-c like the pager itself does. Otherwise the pager is left running and the terminal is in raw
         
     | 
| 
      
 217 
     | 
    
         
            +
                        # mode and unusable.
         
     | 
| 
      
 218 
     | 
    
         
            +
                        pass
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
            def tempfile_pager(text: str, cmd: str, title: str = '') -> None:
         
     | 
| 
      
 222 
     | 
    
         
            +
                """Page through text by invoking a program on a temporary file."""
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                with tempfile.TemporaryDirectory() as tempdir:
         
     | 
| 
      
 225 
     | 
    
         
            +
                    filename = os.path.join(tempdir, 'pydoc.out')
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                    with open(
         
     | 
| 
      
 228 
     | 
    
         
            +
                            filename,
         
     | 
| 
      
 229 
     | 
    
         
            +
                            'w',
         
     | 
| 
      
 230 
     | 
    
         
            +
                            errors='backslashreplace',
         
     | 
| 
      
 231 
     | 
    
         
            +
                            encoding=os.device_encoding(0) if sys.platform == 'win32' else None,
         
     | 
| 
      
 232 
     | 
    
         
            +
                    ) as file:
         
     | 
| 
      
 233 
     | 
    
         
            +
                        file.write(text)
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                    os.system(cmd + ' "' + filename + '"')
         
     |