omlish 0.0.0.dev118__py3-none-any.whl → 0.0.0.dev119__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/lite/journald.py +163 -0
- omlish/lite/logs.py +6 -2
- omlish/logs/_abc.py +53 -0
- omlish/logs/handlers.py +1 -1
- omlish/testing/pytest/plugins/pydevd.py +6 -6
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/RECORD +12 -11
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev118.dist-info → omlish-0.0.0.dev119.dist-info}/top_level.txt +0 -0
    
        omlish/__about__.py
    CHANGED
    
    
    
        omlish/lite/journald.py
    ADDED
    
    | @@ -0,0 +1,163 @@ | |
| 1 | 
            +
            # ruff: noqa: UP007 UP012
         | 
| 2 | 
            +
            import ctypes as ct
         | 
| 3 | 
            +
            import logging
         | 
| 4 | 
            +
            import sys
         | 
| 5 | 
            +
            import syslog
         | 
| 6 | 
            +
            import threading
         | 
| 7 | 
            +
            import typing as ta
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            from .cached import cached_nullary
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            ##
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            class sd_iovec(ct.Structure):  # noqa
         | 
| 16 | 
            +
                pass
         | 
| 17 | 
            +
             | 
| 18 | 
            +
             | 
| 19 | 
            +
            sd_iovec._fields_ = [
         | 
| 20 | 
            +
                ('iov_base', ct.c_void_p),  # Pointer to data.
         | 
| 21 | 
            +
                ('iov_len', ct.c_size_t),  # Length of data.
         | 
| 22 | 
            +
            ]
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            ##
         | 
| 26 | 
            +
             | 
| 27 | 
            +
             | 
| 28 | 
            +
            @cached_nullary
         | 
| 29 | 
            +
            def sd_libsystemd() -> ta.Any:
         | 
| 30 | 
            +
                lib = ct.CDLL('libsystemd.so.0')
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                lib.sd_journal_sendv = lib['sd_journal_sendv']  # type: ignore
         | 
| 33 | 
            +
                lib.sd_journal_sendv.restype = ct.c_int
         | 
| 34 | 
            +
                lib.sd_journal_sendv.argtypes = [ct.POINTER(sd_iovec), ct.c_int]
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                return lib
         | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
            @cached_nullary
         | 
| 40 | 
            +
            def sd_try_libsystemd() -> ta.Optional[ta.Any]:
         | 
| 41 | 
            +
                try:
         | 
| 42 | 
            +
                    return sd_libsystemd()
         | 
| 43 | 
            +
                except OSError:  # noqa
         | 
| 44 | 
            +
                    return None
         | 
| 45 | 
            +
             | 
| 46 | 
            +
             | 
| 47 | 
            +
            ##
         | 
| 48 | 
            +
             | 
| 49 | 
            +
             | 
| 50 | 
            +
            def sd_journald_send(**fields: str) -> int:
         | 
| 51 | 
            +
                lib = sd_libsystemd()
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                msgs = [
         | 
| 54 | 
            +
                    f'{k.upper()}={v}\0'.encode('utf-8')
         | 
| 55 | 
            +
                    for k, v in fields.items()
         | 
| 56 | 
            +
                ]
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                vec = (sd_iovec * len(msgs))()
         | 
| 59 | 
            +
                cl = (ct.c_char_p * len(msgs))()  # noqa
         | 
| 60 | 
            +
                for i in range(len(msgs)):
         | 
| 61 | 
            +
                    vec[i].iov_base = ct.cast(ct.c_char_p(msgs[i]), ct.c_void_p)
         | 
| 62 | 
            +
                    vec[i].iov_len = len(msgs[i]) - 1
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                return lib.sd_journal_sendv(vec, len(msgs))
         | 
| 65 | 
            +
             | 
| 66 | 
            +
             | 
| 67 | 
            +
            ##
         | 
| 68 | 
            +
             | 
| 69 | 
            +
             | 
| 70 | 
            +
            SD_LOG_LEVEL_MAP: ta.Mapping[int, int] = {
         | 
| 71 | 
            +
                logging.FATAL: syslog.LOG_EMERG,  # system is unusable
         | 
| 72 | 
            +
                # LOG_ALERT ?  # action must be taken immediately
         | 
| 73 | 
            +
                logging.CRITICAL: syslog.LOG_CRIT,
         | 
| 74 | 
            +
                logging.ERROR: syslog.LOG_ERR,
         | 
| 75 | 
            +
                logging.WARNING: syslog.LOG_WARNING,
         | 
| 76 | 
            +
                # LOG_NOTICE ?  # normal but significant condition
         | 
| 77 | 
            +
                logging.INFO: syslog.LOG_INFO,
         | 
| 78 | 
            +
                logging.DEBUG: syslog.LOG_DEBUG,
         | 
| 79 | 
            +
            }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
             | 
| 82 | 
            +
            class JournaldLogHandler(logging.Handler):
         | 
| 83 | 
            +
                """
         | 
| 84 | 
            +
                TODO:
         | 
| 85 | 
            +
                 - fallback handler for when this barfs
         | 
| 86 | 
            +
                """
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def __init__(
         | 
| 89 | 
            +
                        self,
         | 
| 90 | 
            +
                        *,
         | 
| 91 | 
            +
                        use_formatter_output: bool = False,
         | 
| 92 | 
            +
                ) -> None:
         | 
| 93 | 
            +
                    super().__init__()
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                    sd_libsystemd()
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    self._use_formatter_output = use_formatter_output
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                #
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                EXTRA_RECORD_ATTRS_BY_JOURNALD_FIELD: ta.ClassVar[ta.Mapping[str, str]] = {
         | 
| 102 | 
            +
                    'name': 'name',
         | 
| 103 | 
            +
                    'module': 'module',
         | 
| 104 | 
            +
                    'exception': 'exc_text',
         | 
| 105 | 
            +
                    'thread_name': 'threadName',
         | 
| 106 | 
            +
                    'task_name': 'taskName',
         | 
| 107 | 
            +
                }
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                def make_fields(self, record: logging.LogRecord) -> ta.Mapping[str, str]:
         | 
| 110 | 
            +
                    formatter_message = self.format(record)
         | 
| 111 | 
            +
                    if self._use_formatter_output:
         | 
| 112 | 
            +
                        message = formatter_message
         | 
| 113 | 
            +
                    else:
         | 
| 114 | 
            +
                        message = record.message
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    fields: dict[str, str] = {
         | 
| 117 | 
            +
                        'message': message,
         | 
| 118 | 
            +
                        'priority': str(SD_LOG_LEVEL_MAP[record.levelno]),
         | 
| 119 | 
            +
                        'tid': str(threading.get_ident()),
         | 
| 120 | 
            +
                    }
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    if (pathname := record.pathname) is not None:
         | 
| 123 | 
            +
                        fields['code_file'] = pathname
         | 
| 124 | 
            +
                    if (lineno := record.lineno) is not None:
         | 
| 125 | 
            +
                        fields['code_lineno'] = str(lineno)
         | 
| 126 | 
            +
                    if (func_name := record.funcName) is not None:
         | 
| 127 | 
            +
                        fields['code_func'] = func_name
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                    for f, a in self.EXTRA_RECORD_ATTRS_BY_JOURNALD_FIELD.items():
         | 
| 130 | 
            +
                        if (v := getattr(record, a, None)) is not None:
         | 
| 131 | 
            +
                            fields[f] = str(v)
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                    return fields
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                #
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                def emit(self, record: logging.LogRecord) -> None:
         | 
| 138 | 
            +
                    try:
         | 
| 139 | 
            +
                        fields = self.make_fields(record)
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                        if rc := sd_journald_send(**fields):
         | 
| 142 | 
            +
                            raise RuntimeError(f'{self.__class__.__name__}.emit failed: {rc=}')  # noqa
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    except RecursionError:  # See issue 36272
         | 
| 145 | 
            +
                        raise
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                    except Exception:  # noqa
         | 
| 148 | 
            +
                        self.handleError(record)
         | 
| 149 | 
            +
             | 
| 150 | 
            +
             | 
| 151 | 
            +
            def journald_log_handler_factory(
         | 
| 152 | 
            +
                    *,
         | 
| 153 | 
            +
                    no_tty_check: bool = False,
         | 
| 154 | 
            +
                    no_fallback: bool = False,
         | 
| 155 | 
            +
            ) -> logging.Handler:
         | 
| 156 | 
            +
                if (
         | 
| 157 | 
            +
                        sys.platform == 'linux' and
         | 
| 158 | 
            +
                        (no_tty_check or not sys.stderr.isatty()) and
         | 
| 159 | 
            +
                        (no_fallback or sd_try_libsystemd() is not None)
         | 
| 160 | 
            +
                ):
         | 
| 161 | 
            +
                    return JournaldLogHandler()
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                return logging.StreamHandler()
         | 
    
        omlish/lite/logs.py
    CHANGED
    
    | @@ -91,7 +91,7 @@ class StandardLogFormatter(logging.Formatter): | |
| 91 91 | 
             
                    if datefmt:
         | 
| 92 92 | 
             
                        return ct.strftime(datefmt)  # noqa
         | 
| 93 93 | 
             
                    else:
         | 
| 94 | 
            -
                        t = ct.strftime( | 
| 94 | 
            +
                        t = ct.strftime('%Y-%m-%d %H:%M:%S')
         | 
| 95 95 | 
             
                        return '%s.%03d' % (t, record.msecs)
         | 
| 96 96 |  | 
| 97 97 |  | 
| @@ -228,6 +228,7 @@ def configure_standard_logging( | |
| 228 228 | 
             
                    json: bool = False,
         | 
| 229 229 | 
             
                    target: ta.Optional[logging.Logger] = None,
         | 
| 230 230 | 
             
                    force: bool = False,
         | 
| 231 | 
            +
                    handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
         | 
| 231 232 | 
             
            ) -> ta.Optional[StandardLogHandler]:
         | 
| 232 233 | 
             
                with _locking_logging_module_lock():
         | 
| 233 234 | 
             
                    if target is None:
         | 
| @@ -241,7 +242,10 @@ def configure_standard_logging( | |
| 241 242 |  | 
| 242 243 | 
             
                    #
         | 
| 243 244 |  | 
| 244 | 
            -
                     | 
| 245 | 
            +
                    if handler_factory is not None:
         | 
| 246 | 
            +
                        handler = handler_factory()
         | 
| 247 | 
            +
                    else:
         | 
| 248 | 
            +
                        handler = logging.StreamHandler()
         | 
| 245 249 |  | 
| 246 250 | 
             
                    #
         | 
| 247 251 |  | 
    
        omlish/logs/_abc.py
    CHANGED
    
    | @@ -16,27 +16,80 @@ ExceptionInfo: ta.TypeAlias = tuple[type[BaseException], BaseException, types.Tr | |
| 16 16 |  | 
| 17 17 |  | 
| 18 18 | 
             
            class LogRecord:
         | 
| 19 | 
            +
                """https://docs.python.org/3/library/logging.html#logrecord-attributes"""
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # Name of the logger used to log the call.
         | 
| 19 22 | 
             
                name: str
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # Human-readable time when the LogRecord was created. By default this is of the form '2003-07-08 16:49:45,896' (the
         | 
| 25 | 
            +
                # numbers after the comma are millisecond portion of the time).
         | 
| 26 | 
            +
                asctime: str
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
         | 
| 29 | 
            +
                message: str
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object
         | 
| 32 | 
            +
                # (see Using arbitrary objects as messages).
         | 
| 20 33 | 
             
                msg: str
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when
         | 
| 36 | 
            +
                # there is only one argument, and it is a dictionary).
         | 
| 21 37 | 
             
                args: tuple
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                # Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
         | 
| 22 40 | 
             
                levelname: str
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                # # Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
         | 
| 23 43 | 
             
                levelno: Level
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # Full pathname of the source file where the logging call was issued (if available).
         | 
| 24 46 | 
             
                pathname: str
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Filename portion of pathname.
         | 
| 25 49 | 
             
                filename: str
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                # Module (name portion of filename).
         | 
| 26 52 | 
             
                module: str
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
         | 
| 27 55 | 
             
                exc_info: ExceptionInfo | None
         | 
| 56 | 
            +
             | 
| 28 57 | 
             
                exc_text: str | None
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                # Stack frame information (where available) from the bottom of the stack in the current thread, up to and including
         | 
| 60 | 
            +
                # the stack frame of the logging call which resulted in the creation of this record.
         | 
| 29 61 | 
             
                stack_info: str | None
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                # Source line number where the logging call was issued (if available).
         | 
| 30 64 | 
             
                lineno: int
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                # Name of function containing the logging call.
         | 
| 31 67 | 
             
                funcName: str
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                # Time when the LogRecord was created (as returned by time.time_ns() / 1e9).
         | 
| 32 70 | 
             
                created: float
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                # Millisecond portion of the time when the LogRecord was created.
         | 
| 33 73 | 
             
                msecs: float
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                # Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
         | 
| 34 76 | 
             
                relativeCreated: float
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                # Thread ID (if available).
         | 
| 35 79 | 
             
                thread: int
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                # Thread name (if available).
         | 
| 36 82 | 
             
                threadName: str
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                # Process name (if available).
         | 
| 37 85 | 
             
                processName: str
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # Process ID (if available).
         | 
| 38 88 | 
             
                process: int
         | 
| 39 89 |  | 
| 90 | 
            +
                # asyncio.Task name (if available).
         | 
| 91 | 
            +
                taskName: str
         | 
| 92 | 
            +
             | 
| 40 93 |  | 
| 41 94 | 
             
            ##
         | 
| 42 95 |  | 
    
        omlish/logs/handlers.py
    CHANGED
    
    
| @@ -16,9 +16,9 @@ class PydevdPlugin: | |
| 16 16 | 
             
                        # if (dbg := opd.get_global_debugger()) is not None:
         | 
| 17 17 | 
             
                        #     dbg.set_unit_tests_debugging_mode()
         | 
| 18 18 |  | 
| 19 | 
            -
                def pytest_exception_interact(self, node, call, report):
         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 19 | 
            +
                # def pytest_exception_interact(self, node, call, report):
         | 
| 20 | 
            +
                #     if opd.get_setup() is not None:
         | 
| 21 | 
            +
                #         if not node.session.config.option.no_pydevd:
         | 
| 22 | 
            +
                #             opd.debug_unhandled_exception(call.excinfo._excinfo)  # noqa
         | 
| 23 | 
            +
                #
         | 
| 24 | 
            +
                #     return report
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            omlish/.manifests.json,sha256=CxGnj-UiRPlZgmgWoovDWrOnqpSEmBy_kqA7cdfSA3w,1431
         | 
| 2 | 
            -
            omlish/__about__.py,sha256= | 
| 2 | 
            +
            omlish/__about__.py,sha256=cKBa887pzxYkOLw1HFwEiT4g4dP8AxuJQrGNkTmiju8,3352
         | 
| 3 3 | 
             
            omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 4 4 | 
             
            omlish/argparse.py,sha256=cqKGAqcxuxv_s62z0gq29L9KAvg_3-_rFvXKjVpRJjo,8126
         | 
| 5 5 | 
             
            omlish/c3.py,sha256=4vogWgwPb8TbNS2KkZxpoWbwjj7MuHG2lQG-hdtkvjI,8062
         | 
| @@ -303,8 +303,9 @@ omlish/lite/check.py,sha256=ouJme9tkzWXKymm_xZDK4mngdYSkxDrok6CSegvf-1w,1015 | |
| 303 303 | 
             
            omlish/lite/contextmanagers.py,sha256=_n6a9xhn06BD8H6A_SDtcipMrSBpzBqcxI0Ob2juomM,1226
         | 
| 304 304 | 
             
            omlish/lite/docker.py,sha256=3IVZZtIm7-UdB2SwArmN_MosTva1_KifyYp3YWjODbE,337
         | 
| 305 305 | 
             
            omlish/lite/io.py,sha256=lcpI1cS_Kn90tvYMg8ZWkSlYloS4RFqXCk-rKyclhdg,3148
         | 
| 306 | 
            +
            omlish/lite/journald.py,sha256=3nfahFbTrdrfp9txhtto6JYAyrus2kcAFtviqdm3qAo,3949
         | 
| 306 307 | 
             
            omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
         | 
| 307 | 
            -
            omlish/lite/logs.py,sha256= | 
| 308 | 
            +
            omlish/lite/logs.py,sha256=tw7mbQslkyo9LopfgQnj0tYiqJ9TDNiw7D07aF7Dm2g,6176
         | 
| 308 309 | 
             
            omlish/lite/marshal.py,sha256=SyYMsJ-TaGO9FX7LykBB0WtqsqetX9eLBotPiz3M_xg,9478
         | 
| 309 310 | 
             
            omlish/lite/pidfile.py,sha256=PRSDOAXmNkNwxh-Vwif0Nrs8RAmWroiNhLKIbdjwzBc,1723
         | 
| 310 311 | 
             
            omlish/lite/reflect.py,sha256=9QYJwdINraq1JNMEgvoqeSlVvRRgOXpxAkpgX8EgRXc,1307
         | 
| @@ -313,10 +314,10 @@ omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816 | |
| 313 314 | 
             
            omlish/lite/strings.py,sha256=QURcE4-1pKVW8eT_5VCJpXaHDWR2dW2pYOChTJnZDiQ,1504
         | 
| 314 315 | 
             
            omlish/lite/subprocesses.py,sha256=_YwUpvfaC2pV5TMC9-Ivuw1Ao-YxteD3a1NQwGERft4,3380
         | 
| 315 316 | 
             
            omlish/logs/__init__.py,sha256=FbOyAW-lGH8gyBlSVArwljdYAU6RnwZLI5LwAfuNnrk,438
         | 
| 316 | 
            -
            omlish/logs/_abc.py,sha256= | 
| 317 | 
            +
            omlish/logs/_abc.py,sha256=rWySJcr1vatu-AR1EYtODRhi-TjFaixqUzXeWg1c0GA,8006
         | 
| 317 318 | 
             
            omlish/logs/configs.py,sha256=EE0jlNaXJbGnM7V-y4xS5VwyTBSTzFzc0BYaVjg0JmA,1283
         | 
| 318 319 | 
             
            omlish/logs/formatters.py,sha256=q79nMnR2mRIStPyGrydQHpYTXgC5HHptt8lH3W2Wwbs,671
         | 
| 319 | 
            -
            omlish/logs/handlers.py,sha256= | 
| 320 | 
            +
            omlish/logs/handlers.py,sha256=UpzUf3kWBBzWOnrtljoZsLjISw3Ix-ePz3Nsmp6lRgE,255
         | 
| 320 321 | 
             
            omlish/logs/noisy.py,sha256=Ubc-eTH6ZbGYsLfUUi69JAotwuUwzb-SJBeGo_0dIZI,348
         | 
| 321 322 | 
             
            omlish/logs/utils.py,sha256=MgGovbP0zUrZ3FGD3qYNQWn-l0jy0Y0bStcQvv5BOmQ,391
         | 
| 322 323 | 
             
            omlish/marshal/__init__.py,sha256=iVA7n31L08Bdub6HKPvYOXVvDhk2CMA6rPeKDL_u1to,2298
         | 
| @@ -457,7 +458,7 @@ omlish/testing/pytest/plugins/asyncs.py,sha256=SV6oKCy50CGkzLGYX-CT4MfWNqsrH8ONE | |
| 457 458 | 
             
            omlish/testing/pytest/plugins/depskip.py,sha256=xithY-OMtjwhv8mcRNkv-WI_PSQtHldQ8H1s60MIXkk,2673
         | 
| 458 459 | 
             
            omlish/testing/pytest/plugins/logging.py,sha256=1zs6Xe54wiaSjabCviaFXwKkoN97CKm3mA5mEoUeJGs,380
         | 
| 459 460 | 
             
            omlish/testing/pytest/plugins/managermarks.py,sha256=AP3ty-QB-8O5DkulwUOudBlUOvXMHhBfNyY-0yCmejk,1520
         | 
| 460 | 
            -
            omlish/testing/pytest/plugins/pydevd.py,sha256= | 
| 461 | 
            +
            omlish/testing/pytest/plugins/pydevd.py,sha256=AXtN83M39ZKJ4VH3MJEhvPnAmYzD5u1r8ehz-0om50Q,842
         | 
| 461 462 | 
             
            omlish/testing/pytest/plugins/repeat.py,sha256=flSQzE9GFOWksVKz-mUGnpxJpv3yRqn1G4K8pW7JHs0,498
         | 
| 462 463 | 
             
            omlish/testing/pytest/plugins/skips.py,sha256=EoZDg1uWccgbAegmzqI85c7RliycD1e2J4Y7vfDRhwM,1041
         | 
| 463 464 | 
             
            omlish/testing/pytest/plugins/spacing.py,sha256=JQQhi9q3c523Ro1a_K_9RGAb7HotiO74N8bYX2VESFE,707
         | 
| @@ -470,9 +471,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329 | |
| 470 471 | 
             
            omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
         | 
| 471 472 | 
             
            omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
         | 
| 472 473 | 
             
            omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
         | 
| 473 | 
            -
            omlish-0.0.0. | 
| 474 | 
            -
            omlish-0.0.0. | 
| 475 | 
            -
            omlish-0.0.0. | 
| 476 | 
            -
            omlish-0.0.0. | 
| 477 | 
            -
            omlish-0.0.0. | 
| 478 | 
            -
            omlish-0.0.0. | 
| 474 | 
            +
            omlish-0.0.0.dev119.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
         | 
| 475 | 
            +
            omlish-0.0.0.dev119.dist-info/METADATA,sha256=sMg30UlhW1GLNw8MkOhVqMaaiObB2IXCn22KIqaMpWU,4000
         | 
| 476 | 
            +
            omlish-0.0.0.dev119.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
         | 
| 477 | 
            +
            omlish-0.0.0.dev119.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
         | 
| 478 | 
            +
            omlish-0.0.0.dev119.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
         | 
| 479 | 
            +
            omlish-0.0.0.dev119.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |