Beispiel #1
0
def test_pretty_class():
    class Foobar:
        def __pretty__(self, fmt, **kwargs):
            yield 'xxx'

    assert pformat(Foobar()) == 'xxx'
    assert pformat(Foobar) == "<class 'tests.test_custom_pretty.test_pretty_class.<locals>.Foobar'>"
Beispiel #2
0
def meet_text_prefix(
    chain: MessageChain,
    command_name: str,
    command_config: CommandConfig,
) -> Tuple[bool, str]:

    aliases: Set[str] = set(command_config.aliases)
    if command_config.include_class_name:
        aliases.add(command_name)
    # aliases.add("")  # 保证下方循环至少执行一次

    if command_config.need_prefix:
        prefixes: Iterable[str] = set(command_config.prefixes)
    else:  # 保证下方循环至少执行一次
        prefixes = [""]

    logger.debug(pformat(command_name))
    logger.debug(pformat(prefixes))
    logger.debug(pformat(aliases))

    for alias in aliases:
        for prefix in prefixes:
            final_prefix = prefix + alias
            logger.debug(pformat(final_prefix))
            if re.search(f"^{final_prefix}", chain.pure_text):
                return True, final_prefix

    return False, ""
Beispiel #3
0
def meet_command_exit(chain: MessageChain, command_config: CommandConfig):
    """退出判断"""

    logger.debug(pformat(command_config.exit_patterns))
    for pattern in command_config.exit_patterns:
        logger.debug(pformat(re.search(pattern, chain.pure_text)))
        if re.search(pattern, chain.pure_text):
            return True

    return False
Beispiel #4
0
def test_devtools_output():
    class MyTestModel(BaseModel):
        a = 1
        b = [1, 2, 3]

    assert devtools.pformat(
        MyTestModel()) == 'MyTestModel(\n    a=1,\n    b=[1, 2, 3],\n)'
Beispiel #5
0
def test_yield_other():
    class CustomCls:
        def __pretty__(self, fmt, **kwargs):
            yield fmt('xxx')
            yield 123

    my_cls = CustomCls()
    v = pformat(my_cls)
    assert v == "'xxx'123"
Beispiel #6
0
def dev(path: StrPath, port: int):
    config = get_config(path)
    config.mode = Mode.development
    logger.debug('Config:\n%s', devtools.pformat(config.dict()))

    _empty_dir(config.dist_dir)
    _empty_dir(config.get_tmp_dir())

    loop = asyncio.get_event_loop()
    return loop.run_until_complete(adev(config, port))
Beispiel #7
0
    async def adjust(
        self, adjustments: list[Adjustment], control: Control
    ) -> Description:
        summary = f"[{', '.join(list(map(str, adjustments)))}]"
        self.logger.info(f"Adjusting... {summary}")
        self.logger.trace(devtools.pformat(adjustments))
        self.logger.trace(devtools.pformat(control))

        aggregate_description = Description.construct()
        results = await self.servo.dispatch_event(
            servo.Events.adjust, adjustments=adjustments, control=control
        )
        for result in results:
            description = result.value
            aggregate_description.components.extend(description.components)
            aggregate_description.metrics.extend(description.metrics)

        self.logger.success(f"Adjustment completed {summary}")
        return aggregate_description
Beispiel #8
0
def test_devtools_compatibility(example_model_factory):
    model = example_model_factory()
    model_class = model.__class__
    formatted_string = devtools.pformat(model)

    assert hasattr(model_class, "__pretty__")
    assert callable(model_class.__pretty__)
    assert f"{model_class.__name__}(" in formatted_string
    for name in model_class.__datamodel_fields__.keys():
        assert f"{name}=" in formatted_string
Beispiel #9
0
async def run_class_handlers(
    protocol: T_BotProtocol,
    mode: T_RouteMode,
    source_id: str,
    raw_event: Dict,
    event_name: str,
    class_handler_names: Set[str],
):
    kwargs = await get_kwargs(protocol, mode, source_id, event_name, raw_event)
    logger.debug(pformat(kwargs))

    for class_handler_name in class_handler_names:
        class_handler_cache = class_handler_mapping[class_handler_name]
        logger.debug(pformat(class_handler_cache))

        event_handler = class_handler_cache.event_handlers.get(event_name)
        # logger.debug(pformat(event_name, event_handler))
        if event_handler:
            logger.info(f"开始执行 {class_handler_name} 的 {event_name} 事件响应")
            await await_or_sync(event_handler, **fit_kwargs(event_handler, kwargs))
Beispiel #10
0
def build(path: StrPath,
          steps: Set[BuildSteps] = None,
          mode: Optional[Mode] = None):
    completed_logger.info('building site...')
    config = get_config(path)
    if mode:
        config.mode = mode
    logger.debug('Config: %s', devtools.pformat(config.dict()))

    steps = steps or ALL_STEPS
    if BuildSteps.extensions in steps:
        config = apply_modifiers(config, config.extensions.config_modifiers)

    clean = BuildSteps.clean in steps
    _empty_dir(config.dist_dir, clean)
    _empty_dir(config.get_tmp_dir(), clean)

    pages = None
    data_future = None
    with ProcessPoolExecutor() as executor:
        futures = [
            BuildSteps.sass in steps
            and executor.submit(assets_grablib, config),
            BuildSteps.webpack in steps
            and executor.submit(run_webpack, config),
        ]

        if BuildSteps.data in steps:
            data_future = executor.submit(load_data, config)

        if BuildSteps.pages in steps:
            pages = build_pages(config)
        # this will raise errors if any of the above went wrong
        [f.result() for f in futures if f]

    som = dict(
        pages=pages,
        data=data_future and data_future.result(),
        config=config,
    )

    if BuildSteps.extensions in steps:
        apply_page_generator(som, config)

    som['path_lookup'] = get_path_lookup(config, pages)

    if BuildSteps.extensions in steps:
        som = apply_modifiers(som, config.extensions.som_modifiers)

    if som['pages'] is not None:
        content_templates(som['pages'].values(), config)
        render_pages(config, som)
    return som
Beispiel #11
0
def test_skip():
    class CustomCls:
        def __pretty__(self, fmt, skip_exc, **kwargs):
            raise skip_exc()
            yield 'Thing()'

        def __repr__(self):
            return '<CustomCls repr>'

    my_cls = CustomCls()
    v = pformat(my_cls)
    assert v == '<CustomCls repr>'
Beispiel #12
0
async def run_command_method(method_name, method, all_locals: Dict) -> Any:
    logger.debug(pformat(all_locals))
    injected_kwargs = dict(
        raw_event=all_locals["raw_event"],
        chain=all_locals["chain"],
        sender=all_locals["sender"],
        history=all_locals["status"].history,
        # context=all_locals["context"],
    )

    if method_name == "cache":
        injected_kwargs["exception"] = all_locals["exception"]

    else:
        if method_name not in COMMAND_LIFECYCLE_EXCEPTIONS.values():
            injected_kwargs = {**injected_kwargs, **all_locals["patterns"]}

    # 参数和group_message/friend_message事件参数一致
    logger.debug(f"将被注入 {method_name} 的参数\n{pformat(injected_kwargs)}")
    result = await await_or_sync(method, **fit_kwargs(method, injected_kwargs))
    logger.debug(pformat(result))
    return result
Beispiel #13
0
async def websocket_receiver(request, ws, protocol: T_BotProtocol):
    while True:
        try:
            data = await ws.recv()
            raw_event = json.loads(data)

            logger.debug(pformat(raw_event))
            await handle_event(protocol, raw_event)

        except EventHandleError as e:
            logger.error(e)

        except Exception:
            logger.exception("事件处理异常")
Beispiel #14
0
async def http_receiver(request, protocol: T_BotProtocol):
    try:
        raw_event = request.json

        logger.debug(pformat(raw_event))
        await handle_event(protocol, raw_event)

    except EventHandleError as e:
        logger.error(e)

    except Exception:
        logger.exception("事件处理异常")

    finally:
        return text("")
Beispiel #15
0
def merge_text_of_segments(
        segments: List[T_SegmentInstance]) -> T_CompressedSegments:
    """合并相邻的Text片段,空格分隔,方便正则"""
    logger.debug(pformat(segments))

    if len(segments) <= 1:
        return segments

    compressed_segments: T_CompressedSegments = []

    text_buffer: List[Text] = []
    last_segment_type = Text
    segments_count = len(segments)

    for index, segment in enumerate(segments, start=1):

        # True, True
        if last_segment_type == Text and isinstance(segment, Text):
            text_buffer.append(segment)

            if index == segments_count:
                compressed_segments.append(
                    merge_multi_text_with_space(*text_buffer))

        # False, True
        elif last_segment_type != Text and isinstance(segment, Text):
            text_buffer.append(segment)

            if index == segments_count:
                compressed_segments.append(
                    merge_multi_text_with_space(*text_buffer))

        # True, False
        elif last_segment_type == Text and not isinstance(segment, Text):
            if text_buffer:
                compressed_segments.append(
                    merge_multi_text_with_space(*text_buffer))
                text_buffer = []

            compressed_segments.append(segment)

        # False, False
        else:
            compressed_segments.append(segment)

        last_segment_type = segment.__class__

    return compressed_segments
Beispiel #16
0
def test_simple():
    class CustomCls:
        def __pretty__(self, fmt, **kwargs):
            yield 'Thing('
            yield 1
            for i in range(3):
                yield fmt(list(range(i)))
                yield ','
                yield 0
            yield -1
            yield ')'

    my_cls = CustomCls()

    v = pformat(my_cls)
    assert v == """\
Beispiel #17
0
def test_devtools_output_validation_error():
    class Model(BaseModel):
        a: int

    with pytest.raises(ValueError) as exc_info:
        Model()
    assert devtools.pformat(
        exc_info.value) == ('ValidationError(\n'
                            "    model='Model',\n"
                            '    errors=[\n'
                            '        {\n'
                            "            'loc': ('a',),\n"
                            "            'msg': 'field required',\n"
                            "            'type': 'value_error.missing',\n"
                            '        },\n'
                            '    ],\n'
                            ')')
Beispiel #18
0
    async def measure(self, param: servo.api.MeasureParams) -> Measurement:
        if isinstance(param, dict):
            # required parsing has failed in api.Mixin._post_event(), run parse_obj to surface the validation errors
            servo.api.MeasureParams.parse_obj(param)
        servo.logger.info(f"Measuring... [metrics={', '.join(param.metrics)}]")
        servo.logger.trace(devtools.pformat(param))

        aggregate_measurement = Measurement.construct()
        results: list[servo.EventResult] = await self.servo.dispatch_event(
            servo.Events.measure, metrics=param.metrics, control=param.control
        )
        for result in results:
            measurement = result.value
            aggregate_measurement.readings.extend(measurement.readings)
            aggregate_measurement.annotations.update(measurement.annotations)

        return aggregate_measurement
Beispiel #19
0
 def formatMessage(self, record):
     msg = super().formatMessage(record)
     if msg[0] != '{':
         return msg
     # json from AccessLogger
     obj = json.loads(msg)
     if self.stream_is_tty:
         # in future we can do clever things about colouring the message based on status code
         msg = '{} {} {}'.format(
             sformat(obj['time'], sformat.magenta),
             sformat(obj['prefix'], sformat.blue),
             sformat(obj['msg'],
                     sformat.dim if obj['dim'] else sformat.reset),
         )
     else:
         msg = '{time} {prefix} {msg}'.format(**obj)
     details = getattr(record, 'details', None)
     if details:
         msg = 'details: {}\n{}'.format(
             pformat(details, highlight=self.stream_is_tty), msg)
     return msg
Beispiel #20
0
v = {
    'foo': {
        'whatever': [3, 2, 1]
    },
    'sentence':
    'hello\nworld',
    'generator': (i * 2 for i in [1, 2, 3]),
    'matrix':
    np.matrix([[1, 2, 3, 4], [50, 60, 70, 80], [900, 1000, 1100, 1200],
               [13000, 14000, 15000, 16000]])
}

# pretty print of v
pprint(v)

# as above without colours, the generator will also be empty as it's already been evaluated
s = pformat(v, highlight=False)
print(s)

pp = PrettyFormat(
    indent_step=2,  # default: 4
    indent_char='.',  # default: space
    repr_strings=True,  # default: False
    simple_cutoff=
    2,  # default: 10 (if repr is below this length it'll be shown on one line)
    width=80,  # default: 120
    yield_from_generators=False  # default: True (whether to evaluate generators)
)

print(pp(v, highlight=True))
Beispiel #21
0
 def __repr__(self):
     return pformat(self)
Beispiel #22
0
    async def exec_command(self) -> servo.api.Status:
        cmd_response = await self._post_event(servo.api.Events.whats_next, None)
        self.logger.info(f"What's Next? => {cmd_response.command}")
        self.logger.trace(devtools.pformat(cmd_response))

        if cmd_response.command == servo.api.Commands.describe:
            description = await self.describe(
                Control(**cmd_response.param.get("control", {}))
            )
            self.logger.success(
                f"Described: {len(description.components)} components, {len(description.metrics)} metrics"
            )
            self.logger.debug(devtools.pformat(description))

            status = servo.api.Status.ok(descriptor=description.__opsani_repr__())
            return await self._post_event(servo.api.Events.describe, status.dict())

        elif cmd_response.command == servo.api.Commands.measure:
            try:
                measurement = await self.measure(cmd_response.param)
                self.logger.success(
                    f"Measured: {len(measurement.readings)} readings, {len(measurement.annotations)} annotations"
                )
                self.logger.trace(devtools.pformat(measurement))
                param = measurement.__opsani_repr__()
            except servo.errors.EventError as error:
                self.logger.error(f"Measurement failed: {error}")
                param = servo.api.Status.from_error(error).dict()
                self.logger.error(f"Responding with {param}")
                self.logger.opt(exception=error).debug("Measure failure details")

            return await self._post_event(servo.api.Events.measure, param)

        elif cmd_response.command == servo.api.Commands.adjust:
            adjustments = servo.api.descriptor_to_adjustments(
                cmd_response.param["state"]
            )
            control = Control(**cmd_response.param.get("control", {}))

            try:
                description = await self.adjust(adjustments, control)
                status = servo.api.Status.ok(state=description.__opsani_repr__())

                components_count = len(description.components)
                settings_count = sum(
                    len(component.settings) for component in description.components
                )
                self.logger.success(
                    f"Adjusted: {components_count} components, {settings_count} settings"
                )
            except servo.EventError as error:
                self.logger.error(f"Adjustment failed: {error}")
                status = servo.api.Status.from_error(error)
                self.logger.error(f"Responding with {status.dict()}")
                self.logger.opt(exception=error).debug("Adjust failure details")

            return await self._post_event(servo.api.Events.adjust, status.dict())

        elif cmd_response.command == servo.api.Commands.sleep:
            # TODO: Model this
            duration = Duration(cmd_response.param.get("duration", 120))
            status = servo.utilities.key_paths.value_for_key_path(
                cmd_response.param, "data.status", None
            )
            reason = servo.utilities.key_paths.value_for_key_path(
                cmd_response.param, "data.reason", "unknown reason"
            )
            msg = f"{status}: {reason}" if status else f"{reason}"
            self.logger.info(f"Sleeping for {duration} ({msg}).")
            await asyncio.sleep(duration.total_seconds())

            # Return a status so we have a simple API contract
            return servo.api.Status(status="ok", message=msg)
        else:
            raise ValueError(f"Unknown command '{cmd_response.command.value}'")
Beispiel #23
0
 def _repr_pretty_(self, printer, cycle) -> None:
     """
     Display hook for the IPython repl.
     """
     printer.text(pformat(self))
Beispiel #24
0
def test_pydantic_pretty():
    class MyModel(pydantic.BaseModel):
        foobar: int = 1

    assert pformat(MyModel()) == 'MyModel(\n    foobar=1,\n)'
    assert pformat(MyModel) == "<class 'tests.test_custom_pretty.test_pydantic_pretty.<locals>.MyModel'>"
Beispiel #25
0
async def handle_event(protocol: T_BotProtocol, raw_event: Dict):
    logger.info("*" * 50)

    if not route_mapping.has_initial:
        await initial_bot_info()
        logger.info("成功获取bot元信息")
        route_mapping.has_initial = True

    adapter = get_adapter(protocol)
    raw_event_name = adapter.get_event_name(raw_event)
    protocol_event_name: str = f"{protocol}_" + raw_event_name

    if protocol == "onebot":
        if not onebot_event_meta.has_skip_buffered_event:
            flag = skip_current_onebot_event(raw_event, raw_event_name)
            if not flag:
                return

        logger.info("onebot 心跳")

    logger.info(f"{protocol}事件 {raw_event_name}")

    class_handler_names: Set[str] = set()
    # 对同一个消息来源,同一个class_handler也只应调用一次
    class_command_names: Set[str] = set()
    # 对同一个消息对象,在处理一次事件时
    # 在global_commands、mapping、validator中重复注册的指令应该只运行一次
    mode: T_RouteMode
    source_id: str
    command_trigger_events: List[str]

    if protocol_event_name in ALL_GROUP_EVENTS:
        mode = "group"
        source_id = get_source_id(protocol, mode, raw_event)
        command_trigger_events = GROUP_COMMAND_TRIGGER_EVENTS

    elif protocol_event_name in ALL_PRIVATE_EVENTS:
        mode = "private"
        source_id = get_source_id(protocol, mode, raw_event)
        command_trigger_events = PRIVATE_COMMAND_TRIGGER_EVENTS

    else:
        raise EventHandleError(f"无效/尚未实现的事件{protocol_event_name}")

    validator_handlers, validator_commands = await with_validators(mode, source_id)

    if protocol_event_name in command_trigger_events:
        # normal
        class_command_names |= route_mapping.global_commands[protocol][mode]
        class_command_names |= route_mapping.mapping[protocol][mode][source_id][
            "commands"
        ]
        class_command_names |= validator_commands

        if class_command_names:
            await run_class_commands(
                protocol, mode, source_id, raw_event, class_command_names
            )

        # lock_user
        # for rule_id, rule in lock_user_mapping.items():
        #     if source_id in rule[protocol]:
        #         await run_class_command(mode="lock_user",rule_id)

        # if mode =="group" or mode =="channel":
        #     lock_source_mapping

        # lock_source

    class_handler_names |= route_mapping.global_handlers[protocol][mode]
    class_handler_names |= route_mapping.mapping[protocol][mode][source_id][
        "class_handlers"
    ]
    class_handler_names |= validator_handlers

    logger.debug(pformat(class_handler_names))

    # 比如group_message这样的实现了统一事件的事件
    # 如果用户同时定义了group_message和onebot_group_message,应该执行两次
    event_mapping = UNIVERSAL_PROTOCOL_EVENT_MAPPING.get(raw_event_name)
    if event_mapping and protocol_event_name in event_mapping:
        await run_class_handlers(
            protocol, mode, source_id, raw_event, raw_event_name, class_handler_names
        )

    await run_class_handlers(
        protocol, mode, source_id, raw_event, protocol_event_name, class_handler_names
    )
Beispiel #26
0
def test_pretty_not_func():
    class Foobar:
        __pretty__ = 1

    assert '<locals>.Foobar object' in pformat(Foobar())
Beispiel #27
0
async def parse_pattern(
    chain: MessageChain,
    sender: "CommandSender",
    method_name,
    cache: CommandMethodCache,
    prefix: str,
    context,
):
    """
    根据签名中的PatternArg,自动解析参数,并转换为对应类型,自动注入函数调用中

    满足pattern放行,如果不满足,会对方法调用进行拦截,
    """

    if not cache.compressed_patterns:
        return {}

    compressed_patterns = cache.compressed_patterns

    # todo pydantic有没有原生的功能
    # 尝试解析,解析失败,报错
    # todo List(展开), Any, Union, List[Union/Any]

    formot_hint = "请按照 "
    for arg_name, arg_type in cache.patterns:
        formot_hint += f"<{arg_name} : {arg_type.__name__}> "
    formot_hint += "的格式输入\n不需要输入<或者>,:右侧是该参数的类型"

    # formot_hint添加prefix
    # if method_name == "initial":

    results = {}

    try:

        compressed_segments = merge_text_of_segments(chain.segments)
        logger.debug(pformat(compressed_segments))

        if len(compressed_segments) != len(compressed_patterns):
            raise PatternFormotError(f"未提供足够参数,应为{len(cache.patterns)}个," +
                                     f"获得{len(chain.segments)}个")

        # 对initial应用pattern的情况,支持prefix
        # 目前仅支持文字prefix
        if method_name == "initial":
            if not isinstance(compressed_segments[0], Text):
                return PatternFormotError("目前仅支持文字前缀")

            with_prefix = compressed_segments[0].content
            without_prefix = re.sub(f"^{prefix}", "", with_prefix)
            compressed_segments[0].content = without_prefix

        results = get_pattern_results(compressed_patterns, compressed_segments)

    except PatternFormotError as e:
        # if on_format_error:
        #     return_text = await await_or_normal(
        #         on_format_error, *args, **kwargs
        #     )
        #     if return_text:
        #         await bot.group_msg(return_text)
        # else:
        await sender.send_message(
            # Text(f"{e}\n{formot_hint if with_formot_hint else ''}")
            Text(f"{e}\n{formot_hint}"))

        logger.exception("指令解析失败")
        raise e

    else:
        # todo patternResults的maxSize

        logger.debug(pformat(results))
        return results