Coverage for tests/test_utilities.py: 100%
92 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-30 23:02 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-30 23:02 +0000
1"""Tests for `bunches.utilities`."""
3from __future__ import annotations
5import dataclasses
7import pytest
9from bunches import Dictionary, Listing, utilities
11from .conftest import Something, Unnamed
14def test_capitalify() -> None:
15 """Tests `_capitalify`."""
16 assert utilities._capitalify('snake_case_name') == 'SnakeCaseName'
17 assert utilities._capitalify('word') == 'Word'
18 assert utilities._capitalify('') == ''
21def test_snakify() -> None:
22 """Tests `_snakify`."""
23 assert utilities._snakify('SnakeCaseName') == 'snake_case_name'
24 assert utilities._snakify('Word') == 'word'
25 assert utilities._snakify('HTTPServer') == 'http_server'
26 assert utilities._snakify('already_snake') == 'already_snake'
29def test_is_sequence() -> None:
30 """Tests `_is_sequence`."""
31 assert utilities._is_sequence([1, 2])
32 assert utilities._is_sequence((1, 2))
33 assert utilities._is_sequence(list)
34 assert not utilities._is_sequence('abc')
35 assert not utilities._is_sequence(str)
36 assert not utilities._is_sequence(b'abc')
37 assert not utilities._is_sequence({'a': 1})
38 assert not utilities._is_sequence({1, 2})
39 assert not utilities._is_sequence(5)
42def test_iterify() -> None:
43 """Tests `_iterify`."""
44 assert list(utilities._iterify(None)) == []
45 assert list(utilities._iterify('abc')) == ['abc']
46 assert list(utilities._iterify(b'abc')) == [b'abc']
47 assert list(utilities._iterify([1, 2])) == [1, 2]
48 assert list(utilities._iterify((1, 2))) == [1, 2]
49 assert list(utilities._iterify(5)) == [5]
50 assert list(utilities._iterify({'a': 1})) == ['a']
53def test_namify() -> None:
54 """Tests `_namify`."""
56 @dataclasses.dataclass
57 class BadName:
58 name: int = 3
60 assert utilities._namify('name') == 'name'
61 assert utilities._namify(Something()) == 'something'
62 assert utilities._namify(Something('other')) == 'other'
63 assert utilities._namify(Unnamed()) == 'unnamed'
64 assert utilities._namify(Unnamed) == 'unnamed'
65 assert utilities._namify(Something) == 'something'
66 assert utilities._namify(test_namify) == 'test_namify'
67 assert utilities._namify(5) == 'int'
68 assert utilities._namify(BadName()) == 'bad_name'
71def test_namify_default() -> None:
72 """Tests the `default` argument of `_namify`."""
74 class Meta(type):
75 """Metaclass whose classes have no usable name."""
77 @property
78 def __name__(cls) -> str: # type: ignore[override]
79 """Returns an empty name.
81 Returns:
82 An empty `str`.
84 """
85 return ''
87 class Nameless(metaclass = Meta):
88 """Class without a usable name."""
90 assert utilities._namify(Nameless(), default = 'fallback') == 'fallback'
91 assert utilities._namify(Nameless()) is None
94def test_return_subset() -> None:
95 """Tests `_return_subset`."""
96 dictionary = Dictionary({'a': 1, 'b': 2}, default_factory = 7)
97 subset = {'a': 1}
98 result = utilities._return_subset(subset, dictionary, 'class')
99 assert isinstance(result, Dictionary)
100 assert result.contents == subset
101 assert result.default_factory is None
102 result = utilities._return_subset(subset, dictionary, 'copy')
103 assert isinstance(result, Dictionary)
104 assert result.contents == subset
105 assert result.default_factory == 7
106 assert result is not dictionary
107 assert dictionary.contents == {'a': 1, 'b': 2}
108 assert utilities._return_subset(subset, dictionary, 'simple') is subset
109 with pytest.raises(ValueError, match = 'returns argument'):
110 utilities._return_subset(
111 subset, dictionary, 'other') # type: ignore[arg-type]
112 listing = Listing([1, 2])
113 assert utilities._return_subset([1], listing, 'class') == Listing([1])
116def test_uniquify() -> None:
117 """Tests `_uniquify`."""
118 assert utilities._uniquify('key', {}) == 'key'
119 assert utilities._uniquify('key', {'other': 1}) == 'key'
120 assert utilities._uniquify('key', {'key': 1}) == 'key2'
121 assert utilities._uniquify('key', {'key': 1, 'key2': 1}) == 'key3'
122 existing = {'key': 1} | {f'key{i}': 1 for i in range(2, 12)}
123 assert utilities._uniquify('key', existing) == 'key12'
124 assert utilities._uniquify('key', {'key': 1}, index = 4) == 'key5'
127def test_uniquify_index() -> None:
128 """Tests `_uniquify` with keys that end in the starting index."""
129 assert utilities._uniquify('v4', {'v4': 1}, index = 4) == 'v45'
130 assert utilities._uniquify('a', {'a': 1, 'a1': 1}, index = 0) == 'a2'
131 assert utilities._uniquify('a', {'a': 1}, index = 0) == 'a1'
134def test_is_sequence_bunches() -> None:
135 """Tests `_is_sequence` with `bunches` classes."""
136 assert utilities._is_sequence(Listing([1]))
137 assert utilities._is_sequence(range(3))
138 assert not utilities._is_sequence(Dictionary({'a': 1}))
141def test_namify_class_with_name_attribute() -> None:
142 """Tests that a class's `name` attribute is not used for the class."""
144 class Named:
145 """Class with a `name` class attribute."""
147 name = 'instance_name'
149 assert utilities._namify(Named()) == 'instance_name'
150 assert utilities._namify(Named) == 'named'