File: test_formatter.py

package info (click to toggle)
streamlink 7.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 5,428 kB
  • sloc: python: 49,104; sh: 184; makefile: 145
file content (98 lines) | stat: -rw-r--r-- 3,534 bytes parent folder | download | duplicates (4)
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
95
96
97
98
from datetime import datetime
from os.path import sep
from pathlib import Path
from string import ascii_letters as alphabet
from unittest.mock import Mock, call, patch

import pytest
from freezegun import freeze_time

from streamlink_cli.utils.formatter import Formatter


class TestCLIFormatter:
    class Obj:
        def __str__(self):
            return "obj"

    @pytest.fixture()
    def mock_replace_chars(self):
        with patch("streamlink_cli.utils.formatter.replace_chars") as mock_replace_chars:
            yield mock_replace_chars

    @pytest.fixture()
    def prop(self):
        return Mock(return_value="prop")

    @pytest.fixture()
    def obj(self):
        return self.Obj()

    @pytest.fixture()
    def formatter(self, prop: Mock, obj: Obj):
        with freeze_time("2000-01-02T03:04:05.000006Z"):
            yield Formatter(
                {
                    "prop": prop,
                    "obj": lambda: obj,
                    "time": datetime.now,
                    "empty": lambda: "",
                    "none": lambda: None,
                },
                {
                    "time": lambda dt, fmt: dt.strftime(fmt),
                },
            )

    def test_title(self, formatter: Formatter):
        assert formatter.title == formatter.format

    def test_path(self, formatter: Formatter, prop: Mock, obj: Obj, mock_replace_chars: Mock):
        mock_replace_chars.side_effect = lambda s, *_: s.upper()

        assert formatter.path("text '{prop}' '{empty}' '{none}'") == Path("text 'PROP' '' ''")
        assert formatter.cache == dict(prop="prop", empty="", none=None)
        assert prop.call_count == 1
        assert mock_replace_chars.call_args_list == [
            call("prop", None),
            call("", None),
            call("", None),
        ]
        mock_replace_chars.reset_mock()

        assert formatter.path("text '{prop}' '{obj}' '{empty}' '{none}'", "foo") == Path("text 'PROP' 'OBJ' '' ''")
        assert formatter.cache == dict(prop="prop", obj=obj, empty="", none=None)
        assert prop.call_count == 1
        assert mock_replace_chars.call_args_list == [
            call("prop", "foo"),
            call("obj", "foo"),
            call("", "foo"),
            call("", "foo"),
        ]

    def test_path_substitute(self, formatter: Formatter):
        formatter.mapping.update({
            "current": lambda: ".",
            "parent": lambda: "..",
            "dots": lambda: "...",
            "separator": lambda: sep,
        })
        path = formatter.path(f"{{current}}{sep}{{parent}}{sep}{{dots}}{sep}{{separator}}{sep}foo{sep}.{sep}..{sep}bar")
        assert path == Path("_", "_", "...", "_", "foo", ".", "..", "bar"), \
            "Formats the path's parts separately and ignores current and parent directories in substitutions only"  # fmt: skip

    def test_path_truncation_ascii(self, formatter: Formatter):
        formatter.mapping.update({
            "dir": lambda: alphabet * 10,
            "file": lambda: alphabet * 10,
        })
        path = formatter.path(f"{{dir}}.fakeext{sep}{{file}}.ext")
        assert path == Path((alphabet * 10)[:255], f"{(alphabet * 10)[:251]}.ext")

    def test_path_truncation_unicode(self, formatter: Formatter):
        formatter.mapping.update({
            "dir": lambda: "🐻" * 512,
            "file": lambda: "🐻" * 512,
        })
        path = formatter.path(f"{{dir}}.fakeext{sep}{{file}}.ext")
        assert path == Path("🐻" * 63, f"{'🐻' * 62}.ext")