|
8 | 8 | import re
|
9 | 9 | import sys
|
10 | 10 | from datetime import datetime
|
| 11 | +from enum import Enum |
11 | 12 | from typing import Any
|
12 | 13 | from unittest import mock
|
13 | 14 |
|
|
31 | 32 | from logfire.testing import TestExporter
|
32 | 33 | from tests.utils import ReadableSpanModel, SpanContextModel, exported_spans_as_models
|
33 | 34 |
|
| 35 | +if sys.version_info >= (3, 11): # pragma: no branch |
| 36 | + from enum import IntEnum, StrEnum |
| 37 | +else: # pragma: no cover |
| 38 | + |
| 39 | + class StrEnum(str, Enum): ... |
| 40 | + |
| 41 | + class IntEnum(int, Enum): ... |
| 42 | + |
| 43 | + |
34 | 44 | tracer = trace.get_tracer('test')
|
35 | 45 |
|
36 | 46 | NANOSECONDS_PER_SECOND = int(1e9)
|
@@ -1019,3 +1029,84 @@ def test_console_exporter_list_data_with_object_schema_mismatch(capsys: pytest.C
|
1019 | 1029 | "│ bar={'name': 'Alice', 'age': 30}",
|
1020 | 1030 | ]
|
1021 | 1031 | )
|
| 1032 | + |
| 1033 | + |
| 1034 | +def test_console_exporter_log_pydantic_root_model(capsys: pytest.CaptureFixture[str]) -> None: |
| 1035 | + from pydantic import BaseModel, RootModel |
| 1036 | + |
| 1037 | + logfire.configure( |
| 1038 | + send_to_logfire=False, |
| 1039 | + console=ConsoleOptions(verbose=True, colors='never', include_timestamps=False), |
| 1040 | + ) |
| 1041 | + |
| 1042 | + class Model(BaseModel): |
| 1043 | + name: str |
| 1044 | + |
| 1045 | + class Color(StrEnum): |
| 1046 | + red = 'RED' |
| 1047 | + |
| 1048 | + class Order(IntEnum): |
| 1049 | + one = 1 |
| 1050 | + |
| 1051 | + RootWithModel = RootModel[Model] |
| 1052 | + RootWithStr = RootModel[str] |
| 1053 | + RootWithInt = RootModel[int] |
| 1054 | + RootWithFloat = RootModel[float] |
| 1055 | + RootWithBool = RootModel[bool] |
| 1056 | + RootWithNone = RootModel[None] |
| 1057 | + # enums (which are subclasses of their base types) |
| 1058 | + RootWithColor = RootModel[Color] |
| 1059 | + RootWithOrder = RootModel[Order] |
| 1060 | + |
| 1061 | + model = Model(name='with_model') |
| 1062 | + root_with_model = RootWithModel(root=model) |
| 1063 | + root_with_str = RootWithStr('with_str') |
| 1064 | + root_with_int = RootWithInt(-150) |
| 1065 | + root_with_float = RootWithFloat(2.0) |
| 1066 | + root_with_bool = RootWithBool(False) |
| 1067 | + root_with_none = RootWithNone(None) |
| 1068 | + root_with_color = RootWithColor(Color.red) |
| 1069 | + root_with_order = RootWithOrder(Order.one) |
| 1070 | + |
| 1071 | + logfire.info( |
| 1072 | + 'hi', |
| 1073 | + with_model=root_with_model, |
| 1074 | + with_str=root_with_str, |
| 1075 | + with_str_inner=root_with_str.root, |
| 1076 | + with_int=root_with_int, |
| 1077 | + with_int_inner=root_with_int.root, |
| 1078 | + with_float=root_with_float, |
| 1079 | + with_float_inner=root_with_float.root, |
| 1080 | + with_bool=root_with_bool, |
| 1081 | + with_bool_inner=root_with_bool.root, |
| 1082 | + with_none=root_with_none, |
| 1083 | + with_none_inner=root_with_none.root, |
| 1084 | + with_color=root_with_color, |
| 1085 | + with_color_inner=root_with_color.root, |
| 1086 | + with_order=root_with_order, |
| 1087 | + with_order_inner=root_with_order.root, |
| 1088 | + ) |
| 1089 | + |
| 1090 | + assert capsys.readouterr().out.splitlines() == snapshot( |
| 1091 | + [ |
| 1092 | + 'hi', |
| 1093 | + IsStr(), |
| 1094 | + '│ with_model=Model(', |
| 1095 | + "│ name='with_model',", |
| 1096 | + '│ )', |
| 1097 | + "│ with_str='with_str'", |
| 1098 | + "│ with_str_inner='with_str'", |
| 1099 | + '│ with_int=-150', |
| 1100 | + '│ with_int_inner=-150', |
| 1101 | + '│ with_float=2.0', |
| 1102 | + '│ with_float_inner=2.0', |
| 1103 | + '│ with_bool=False', |
| 1104 | + '│ with_bool_inner=False', |
| 1105 | + '│ with_none=None', |
| 1106 | + '│ with_none_inner=None', |
| 1107 | + "│ with_color=Color('RED')", |
| 1108 | + "│ with_color_inner=Color('RED')", |
| 1109 | + '│ with_order=Order(1)', |
| 1110 | + '│ with_order_inner=Order(1)', |
| 1111 | + ] |
| 1112 | + ) |
0 commit comments