File: test_arrow_backend.py

package info (click to toggle)
textual-fastdatatable 0.12.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,856 kB
  • sloc: python: 3,461; makefile: 24
file content (94 lines) | stat: -rw-r--r-- 3,232 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from __future__ import annotations

from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Sequence

import pyarrow as pa
from textual_fastdatatable import ArrowBackend


def test_from_records(records: list[tuple[str | int, ...]]) -> None:
    backend = ArrowBackend.from_records(records, has_header=True)
    assert backend.column_count == 3
    assert backend.row_count == 5
    assert tuple(backend.columns) == records[0]


def test_from_records_no_header(records: list[tuple[str | int, ...]]) -> None:
    backend = ArrowBackend.from_records(records[1:], has_header=False)
    assert backend.column_count == 3
    assert backend.row_count == 5
    assert tuple(backend.columns) == ("f0", "f1", "f2")


def test_from_pydict(pydict: dict[str, Sequence[str | int]]) -> None:
    backend = ArrowBackend.from_pydict(pydict)
    assert backend.column_count == 3
    assert backend.row_count == 5
    assert backend.source_row_count == 5
    assert tuple(backend.columns) == tuple(pydict.keys())


def test_from_pydict_with_limit(pydict: dict[str, Sequence[str | int]]) -> None:
    backend = ArrowBackend.from_pydict(pydict, max_rows=2)
    assert backend.column_count == 3
    assert backend.row_count == 2
    assert backend.source_row_count == 5
    assert tuple(backend.columns) == tuple(pydict.keys())


def test_from_parquet(pydict: dict[str, Sequence[str | int]], tmp_path: Path) -> None:
    tbl = pa.Table.from_pydict(pydict)
    p = tmp_path / "test.parquet"
    pa.parquet.write_table(tbl, str(p))

    backend = ArrowBackend.from_parquet(p)
    assert backend.data.equals(tbl)


def test_empty_query() -> None:
    data: dict[str, list] = {"a": []}
    backend = ArrowBackend.from_pydict(data)
    assert backend.column_content_widths == [0]


def test_dupe_column_labels() -> None:
    arr = pa.array([0, 1, 2, 3])
    tab = pa.table([arr] * 3, names=["a", "a", "a"])
    backend = ArrowBackend(data=tab)
    assert backend.column_count == 3
    assert backend.row_count == 4
    assert backend.get_row_at(2) == [2, 2, 2]


def test_timestamp_with_tz() -> None:
    """
    Ensure datetimes with offsets but no names do not crash the data table
    when casting to string.
    """
    dt = datetime(2024, 1, 1, hour=15, tzinfo=timezone(offset=timedelta(hours=-5)))
    arr = pa.array([dt, dt, dt])
    tab = pa.table([arr], names=["created_at"])
    backend = ArrowBackend(data=tab)
    assert backend.column_content_widths == [29]


def test_mixed_types() -> None:
    data = [(1000,), ("hi",)]
    backend = ArrowBackend.from_records(records=data)
    assert backend
    assert backend.row_count == 2
    assert backend.get_row_at(0) == ["1000"]
    assert backend.get_row_at(1) == ["hi"]


def test_negative_timestamps() -> None:
    dt = datetime(1, 1, 1, tzinfo=timezone.utc)
    arr = pa.array([dt, dt, dt], type=pa.timestamp("s", tz="America/New_York"))
    tab = pa.table([arr], names=["created_at"])
    backend = ArrowBackend(data=tab)
    assert backend.column_content_widths == [26]
    assert backend.get_column_at(0) == [datetime.min, datetime.min, datetime.min]
    assert backend.get_row_at(0) == [datetime.min]
    assert backend.get_cell_at(0, 0) is datetime.min