Skip to content

Commit 6ab0661

Browse files
authored
Don't truncate numpy array dimensions below max (#792)
1 parent bc9894b commit 6ab0661

File tree

9 files changed

+315
-1393
lines changed

9 files changed

+315
-1393
lines changed

docs/plugins/build_llms_txt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def on_page_content(html: str, page: Page, config: MkDocsConfig, files: Files) -
2727

2828
# The API reference generates HTML tables with line numbers, this strips the line numbers cell and goes back to a code block
2929
for extra in soup.find_all('table', attrs={'class': 'highlighttable'}):
30-
extra.replace_with(BeautifulSoup(f'<pre>{extra.find('code').get_text()}</pre>', 'html.parser'))
30+
extra.replace_with(BeautifulSoup(f'<pre>{extra.find("code").get_text()}</pre>', 'html.parser'))
3131

3232
with open(os.path.join(config.site_dir, 'llms.txt'), 'a', encoding='utf-8') as f:
3333
f.write(MarkdownConverter().convert_soup(soup)) # type: ignore[reportUnknownMemberType]

logfire/_internal/integrations/llm_providers/anthropic.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def is_async_client(
9292
"""Returns whether or not the `client` class is async."""
9393
if issubclass(client, (anthropic.Anthropic, anthropic.AnthropicBedrock)):
9494
return False
95-
assert issubclass(
96-
client, (anthropic.AsyncAnthropic, anthropic.AsyncAnthropicBedrock)
97-
), f'Expected Anthropic, AsyncAnthropic, AnthropicBedrock or AsyncAnthropicBedrock type, got: {client}'
95+
assert issubclass(client, (anthropic.AsyncAnthropic, anthropic.AsyncAnthropicBedrock)), (
96+
f'Expected Anthropic, AsyncAnthropic, AnthropicBedrock or AsyncAnthropicBedrock type, got: {client}'
97+
)
9898
return True

logfire/_internal/json_encoder.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,10 @@ def _numpy_array_encoder(o: Any, seen: set[int]) -> JsonValue:
135135
o = o.A # type: ignore[reportUnknownMemberType]
136136

137137
for dimension in range(dimensions):
138+
if shape[dimension] <= NUMPY_DIMENSION_MAX_SIZE:
139+
continue
138140
# In case of multiple dimensions, we limit the dimension size by the NUMPY_DIMENSION_MAX_SIZE.
139-
half = min(shape[dimension], NUMPY_DIMENSION_MAX_SIZE) // 2
141+
half = NUMPY_DIMENSION_MAX_SIZE // 2
140142
# Slicing and concatenating arrays along the specified axis
141143
slices = [slice(None)] * dimensions
142144
slices[dimension] = slice(0, half)

logfire/_internal/json_schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def _numpy_schema(obj: Any, seen: set[int]) -> JsonDict:
328328
return {
329329
'type': 'array',
330330
'x-python-datatype': 'ndarray',
331-
'x-shape': to_json_value(obj.shape, seen), # type: ignore[reportUnknownMemberType]
331+
'x-shape': to_json_value(obj.shape, seen),
332332
'x-dtype': str(obj.dtype), # type: ignore
333333
}
334334

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ docs = [
179179

180180
[tool.inline-snapshot]
181181
default-flags = ["disable"]
182+
format-command="ruff format --stdin-filename {filename}"
182183

183184
[tool.uv.sources]
184185
logfire-api = { workspace = true }

tests/test_console_exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ def test_exception(exporter: TestExporter) -> None:
776776
SimpleConsoleSpanExporter(output=out, colors='always').export(exporter.exported_spans)
777777
assert out.getvalue().splitlines() == [
778778
'\x1b[32m00:00:01.000\x1b[0m \x1b[31merror!!! test\x1b[0m',
779-
'\x1b[34m │ \x1b[0m\x1b[1;31mZeroDivisionError: ' '\x1b[0mdivision by zero',
779+
'\x1b[34m │ \x1b[0m\x1b[1;31mZeroDivisionError: \x1b[0mdivision by zero',
780780
'\x1b[97;49m \x1b[0m\x1b[35;49m│\x1b[0m\x1b[97;49m '
781781
'\x1b[0m\x1b[97;49mTraceback\x1b[0m\x1b[97;49m '
782782
'\x1b[0m\x1b[97;49m(\x1b[0m\x1b[97;49mmost\x1b[0m\x1b[97;49m '

tests/test_json_args.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ class StrSubclass(str):
823823
pytest.param(
824824
[{str: bytes, int: float}],
825825
"[{<class 'str'>: <class 'bytes'>, <class 'int'>: <class 'float'>}]",
826-
'[{"<class \'str\'>":"<class \'bytes\'>","<class \'int\'>":"<class ' "'float'>\"}]",
826+
'[{"<class \'str\'>":"<class \'bytes\'>","<class \'int\'>":"<class \'float\'>"}]',
827827
{
828828
'items': {
829829
'properties': {
@@ -1235,3 +1235,83 @@ class Model:
12351235
}
12361236
]
12371237
)
1238+
1239+
1240+
def test_numpy_array_truncation(exporter: TestExporter):
1241+
logfire.info('hi', m=numpy.arange(13 * 3 * 11).reshape(13, 3, 11))
1242+
1243+
truncated = [
1244+
[
1245+
[0, 1, 2, 3, 4, 6, 7, 8, 9, 10],
1246+
[11, 12, 13, 14, 15, 17, 18, 19, 20, 21],
1247+
[22, 23, 24, 25, 26, 28, 29, 30, 31, 32],
1248+
],
1249+
[
1250+
[33, 34, 35, 36, 37, 39, 40, 41, 42, 43],
1251+
[44, 45, 46, 47, 48, 50, 51, 52, 53, 54],
1252+
[55, 56, 57, 58, 59, 61, 62, 63, 64, 65],
1253+
],
1254+
[
1255+
[66, 67, 68, 69, 70, 72, 73, 74, 75, 76],
1256+
[77, 78, 79, 80, 81, 83, 84, 85, 86, 87],
1257+
[88, 89, 90, 91, 92, 94, 95, 96, 97, 98],
1258+
],
1259+
[
1260+
[99, 100, 101, 102, 103, 105, 106, 107, 108, 109],
1261+
[110, 111, 112, 113, 114, 116, 117, 118, 119, 120],
1262+
[121, 122, 123, 124, 125, 127, 128, 129, 130, 131],
1263+
],
1264+
[
1265+
[132, 133, 134, 135, 136, 138, 139, 140, 141, 142],
1266+
[143, 144, 145, 146, 147, 149, 150, 151, 152, 153],
1267+
[154, 155, 156, 157, 158, 160, 161, 162, 163, 164],
1268+
],
1269+
[
1270+
[264, 265, 266, 267, 268, 270, 271, 272, 273, 274],
1271+
[275, 276, 277, 278, 279, 281, 282, 283, 284, 285],
1272+
[286, 287, 288, 289, 290, 292, 293, 294, 295, 296],
1273+
],
1274+
[
1275+
[297, 298, 299, 300, 301, 303, 304, 305, 306, 307],
1276+
[308, 309, 310, 311, 312, 314, 315, 316, 317, 318],
1277+
[319, 320, 321, 322, 323, 325, 326, 327, 328, 329],
1278+
],
1279+
[
1280+
[330, 331, 332, 333, 334, 336, 337, 338, 339, 340],
1281+
[341, 342, 343, 344, 345, 347, 348, 349, 350, 351],
1282+
[352, 353, 354, 355, 356, 358, 359, 360, 361, 362],
1283+
],
1284+
[
1285+
[363, 364, 365, 366, 367, 369, 370, 371, 372, 373],
1286+
[374, 375, 376, 377, 378, 380, 381, 382, 383, 384],
1287+
[385, 386, 387, 388, 389, 391, 392, 393, 394, 395],
1288+
],
1289+
[
1290+
[396, 397, 398, 399, 400, 402, 403, 404, 405, 406],
1291+
[407, 408, 409, 410, 411, 413, 414, 415, 416, 417],
1292+
[418, 419, 420, 421, 422, 424, 425, 426, 427, 428],
1293+
],
1294+
]
1295+
assert numpy.array(truncated).shape == (10, 3, 10)
1296+
assert exporter.exported_spans_as_dict() == snapshot(
1297+
[
1298+
{
1299+
'name': 'hi',
1300+
'context': {'trace_id': 1, 'span_id': 1, 'is_remote': False},
1301+
'parent': None,
1302+
'start_time': 1000000000,
1303+
'end_time': 1000000000,
1304+
'attributes': {
1305+
'logfire.span_type': 'log',
1306+
'logfire.level_num': 9,
1307+
'logfire.msg_template': 'hi',
1308+
'logfire.msg': 'hi',
1309+
'code.filepath': 'test_json_args.py',
1310+
'code.function': 'test_numpy_array_truncation',
1311+
'code.lineno': 123,
1312+
'm': IsJson(truncated),
1313+
'logfire.json_schema': '{"type":"object","properties":{"m":{"type":"array","x-python-datatype":"ndarray","x-shape":[13,3,11],"x-dtype":"int64"}}}',
1314+
},
1315+
}
1316+
]
1317+
)

tests/test_tail_sampling.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ def test_span_levels():
487487

488488
def test_invalid_rates():
489489
with inline_snapshot.extra.raises(
490-
snapshot('ValueError: Invalid sampling rates, ' 'must be 0.0 <= background_rate <= head <= 1.0')
490+
snapshot('ValueError: Invalid sampling rates, must be 0.0 <= background_rate <= head <= 1.0')
491491
):
492492
logfire.SamplingOptions.level_or_duration(background_rate=-1)
493493
with pytest.raises(ValueError):
@@ -502,7 +502,7 @@ def test_trace_sample_rate(config_kwargs: dict[str, Any]):
502502
assert logfire.DEFAULT_LOGFIRE_INSTANCE.config.sampling.head == 0.123
503503
assert len(warnings) == 1
504504
assert str(warnings[0].message) == snapshot(
505-
'The `trace_sample_rate` argument is deprecated. ' 'Use `sampling=logfire.SamplingOptions(head=...)` instead.'
505+
'The `trace_sample_rate` argument is deprecated. Use `sampling=logfire.SamplingOptions(head=...)` instead.'
506506
)
507507

508508

0 commit comments

Comments
 (0)