arelle-release 2.37.17__py3-none-any.whl → 2.37.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arelle-release might be problematic. Click here for more details.
- arelle/CntlrWinMain.py +4 -1
- arelle/ModelValue.py +1 -0
- arelle/PythonUtil.py +132 -24
- arelle/ViewWinTree.py +15 -9
- arelle/_version.py +2 -2
- arelle/plugin/OimTaxonomy/ModelValueMore.py +15 -0
- arelle/plugin/OimTaxonomy/ValidateDTS.py +484 -0
- arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +240 -0
- arelle/plugin/OimTaxonomy/XbrlAbstract.py +16 -0
- arelle/plugin/OimTaxonomy/XbrlConcept.py +67 -0
- arelle/plugin/OimTaxonomy/XbrlConst.py +261 -0
- arelle/plugin/OimTaxonomy/XbrlCube.py +91 -0
- arelle/plugin/OimTaxonomy/XbrlDimension.py +38 -0
- arelle/plugin/OimTaxonomy/XbrlDts.py +152 -0
- arelle/plugin/OimTaxonomy/XbrlEntity.py +16 -0
- arelle/plugin/OimTaxonomy/XbrlGroup.py +22 -0
- arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +22 -0
- arelle/plugin/OimTaxonomy/XbrlLabel.py +31 -0
- arelle/plugin/OimTaxonomy/XbrlNetwork.py +100 -0
- arelle/plugin/OimTaxonomy/XbrlProperty.py +28 -0
- arelle/plugin/OimTaxonomy/XbrlReference.py +33 -0
- arelle/plugin/OimTaxonomy/XbrlReport.py +24 -0
- arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +35 -0
- arelle/plugin/OimTaxonomy/XbrlTaxonomy.py +93 -0
- arelle/plugin/OimTaxonomy/XbrlTaxonomyObject.py +154 -0
- arelle/plugin/OimTaxonomy/XbrlTransform.py +17 -0
- arelle/plugin/OimTaxonomy/XbrlTypes.py +23 -0
- arelle/plugin/OimTaxonomy/XbrlUnit.py +17 -0
- arelle/plugin/OimTaxonomy/__init__.py +1038 -0
- arelle/plugin/OimTaxonomy/resources/iso4217.json +4479 -0
- arelle/plugin/OimTaxonomy/resources/oim-taxonomy-schema.json +935 -0
- arelle/plugin/OimTaxonomy/resources/ref.json +333 -0
- arelle/plugin/OimTaxonomy/resources/transform-types.json +2481 -0
- arelle/plugin/OimTaxonomy/resources/types.json +727 -0
- arelle/plugin/OimTaxonomy/resources/utr.json +3046 -0
- arelle/plugin/OimTaxonomy/resources/xbrlSpec.json +1082 -0
- arelle/plugin/saveOIMTaxonomy.py +311 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +36 -2
- arelle/plugin/validate/NL/__init__.py +3 -0
- arelle/plugin/validate/NL/rules/nl_kvk.py +84 -2
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/METADATA +2 -1
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/RECORD +54 -19
- tests/integration_tests/validation/README.md +2 -0
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +15 -4
- tests/integration_tests/validation/run_conformance_suites.py +10 -1
- tests/integration_tests/validation/validation_util.py +10 -5
- tests/unit_tests/arelle/test_frozen_dict.py +176 -0
- tests/unit_tests/arelle/test_frozen_ordered_set.py +315 -0
- tests/unit_tests/arelle/test_import.py +31 -0
- tests/unit_tests/arelle/test_ordered_set.py +272 -0
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.17.dist-info → arelle_release-2.37.19.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from arelle.PythonUtil import FrozenOrderedSet, OrderedSet
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestFrozenOrderedSet:
|
|
9
|
+
def test_empty_initialization(self):
|
|
10
|
+
fos = FrozenOrderedSet()
|
|
11
|
+
assert len(fos) == 0
|
|
12
|
+
assert not fos
|
|
13
|
+
assert list(fos) == []
|
|
14
|
+
|
|
15
|
+
def test_initialization_with_list(self):
|
|
16
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
17
|
+
assert list(fos) == [1, 2, 3]
|
|
18
|
+
assert len(fos) == 3
|
|
19
|
+
|
|
20
|
+
def test_initialization_with_tuple(self):
|
|
21
|
+
fos = FrozenOrderedSet((4, 5, 6))
|
|
22
|
+
assert list(fos) == [4, 5, 6]
|
|
23
|
+
|
|
24
|
+
def test_initialization_with_string(self):
|
|
25
|
+
fos = FrozenOrderedSet("abc")
|
|
26
|
+
assert list(fos) == ["a", "b", "c"]
|
|
27
|
+
|
|
28
|
+
def test_initialization_with_set(self):
|
|
29
|
+
fos = FrozenOrderedSet({7, 8, 9})
|
|
30
|
+
assert len(fos) == 3
|
|
31
|
+
assert 7 in fos
|
|
32
|
+
assert 8 in fos
|
|
33
|
+
assert 9 in fos
|
|
34
|
+
|
|
35
|
+
def test_initialization_with_ordered_set(self):
|
|
36
|
+
fos = FrozenOrderedSet(OrderedSet([7, 8, 9]))
|
|
37
|
+
assert len(fos) == 3
|
|
38
|
+
assert 7 in fos
|
|
39
|
+
assert 8 in fos
|
|
40
|
+
assert 9 in fos
|
|
41
|
+
|
|
42
|
+
def test_initialization_with_duplicates(self):
|
|
43
|
+
fos = FrozenOrderedSet([1, 2, 2, 3, 1, 4])
|
|
44
|
+
assert list(fos) == [1, 2, 3, 4]
|
|
45
|
+
assert len(fos) == 4
|
|
46
|
+
|
|
47
|
+
def test_contains(self):
|
|
48
|
+
fos = FrozenOrderedSet([1, 2, 3, "a", "b"])
|
|
49
|
+
|
|
50
|
+
assert 1 in fos
|
|
51
|
+
assert 2 in fos
|
|
52
|
+
assert 3 in fos
|
|
53
|
+
|
|
54
|
+
assert 4 not in fos
|
|
55
|
+
assert None not in fos
|
|
56
|
+
|
|
57
|
+
def test_len(self):
|
|
58
|
+
assert len(FrozenOrderedSet()) == 0
|
|
59
|
+
assert len(FrozenOrderedSet([1])) == 1
|
|
60
|
+
assert len(FrozenOrderedSet([1, 2, 3])) == 3
|
|
61
|
+
assert len(FrozenOrderedSet([1, 1, 2, 2, 3])) == 3
|
|
62
|
+
|
|
63
|
+
def test_iteration(self):
|
|
64
|
+
fos = FrozenOrderedSet(["first", "second", "third"])
|
|
65
|
+
result = []
|
|
66
|
+
for item in fos:
|
|
67
|
+
result.append(item)
|
|
68
|
+
assert result == ["first", "second", "third"]
|
|
69
|
+
|
|
70
|
+
def test_reversed_iteration(self):
|
|
71
|
+
fos = FrozenOrderedSet(["first", "second", "third"])
|
|
72
|
+
result = list(reversed(fos))
|
|
73
|
+
assert result == ["third", "second", "first"]
|
|
74
|
+
|
|
75
|
+
def test_repr(self):
|
|
76
|
+
# Empty set
|
|
77
|
+
fos_empty = FrozenOrderedSet()
|
|
78
|
+
assert repr(fos_empty) == "FrozenOrderedSet()"
|
|
79
|
+
|
|
80
|
+
# Non-empty set
|
|
81
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
82
|
+
assert repr(fos) == "FrozenOrderedSet((1, 2, 3))"
|
|
83
|
+
|
|
84
|
+
# With strings
|
|
85
|
+
fos_str = FrozenOrderedSet(["a", "b"])
|
|
86
|
+
assert repr(fos_str) == "FrozenOrderedSet(('a', 'b'))"
|
|
87
|
+
|
|
88
|
+
def test_equality_with_frozen_ordered_set(self):
|
|
89
|
+
fos1 = FrozenOrderedSet([1, 2, 3])
|
|
90
|
+
fos2 = FrozenOrderedSet([1, 2, 3])
|
|
91
|
+
fos3 = FrozenOrderedSet([3, 2, 1])
|
|
92
|
+
fos4 = FrozenOrderedSet([1, 2, 3, 4])
|
|
93
|
+
|
|
94
|
+
assert fos1 == fos2
|
|
95
|
+
assert fos1 != fos3
|
|
96
|
+
assert fos1 != fos4
|
|
97
|
+
assert FrozenOrderedSet() == FrozenOrderedSet()
|
|
98
|
+
|
|
99
|
+
def test_equality_with_ordered_set(self):
|
|
100
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
101
|
+
os1 = OrderedSet([1, 2, 3])
|
|
102
|
+
os2 = OrderedSet([3, 2, 1])
|
|
103
|
+
|
|
104
|
+
assert fos == os1
|
|
105
|
+
assert fos != os2
|
|
106
|
+
|
|
107
|
+
def test_equality_with_other_iterables(self):
|
|
108
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
109
|
+
|
|
110
|
+
assert fos == {1, 2, 3}
|
|
111
|
+
assert fos == {3, 2, 1}
|
|
112
|
+
assert fos == [1, 2, 3]
|
|
113
|
+
assert fos == [3, 2, 1]
|
|
114
|
+
assert fos == (1, 2, 3)
|
|
115
|
+
assert fos == (3, 2, 1)
|
|
116
|
+
assert fos != [1, 2, 4]
|
|
117
|
+
assert fos != {1, 2, 4}
|
|
118
|
+
|
|
119
|
+
def test_equality_with_non_iterables(self):
|
|
120
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
121
|
+
|
|
122
|
+
assert fos != 42
|
|
123
|
+
assert fos != "123"
|
|
124
|
+
assert fos != None
|
|
125
|
+
|
|
126
|
+
def test_hashable(self):
|
|
127
|
+
fos1 = FrozenOrderedSet([1, 2, 3])
|
|
128
|
+
fos2 = FrozenOrderedSet([1, 2, 3])
|
|
129
|
+
fos3 = FrozenOrderedSet([3, 2, 1])
|
|
130
|
+
|
|
131
|
+
assert hash(fos1) == hash(fos2)
|
|
132
|
+
assert hash(fos1) != hash(fos3)
|
|
133
|
+
|
|
134
|
+
d = {fos1: "value1", fos3: "value3"}
|
|
135
|
+
assert d[fos1] == "value1"
|
|
136
|
+
assert d[fos2] == "value1"
|
|
137
|
+
assert d[fos3] == "value3"
|
|
138
|
+
|
|
139
|
+
s = {fos1, fos2, fos3}
|
|
140
|
+
assert len(s) == 2
|
|
141
|
+
|
|
142
|
+
def test_hash_consistency(self):
|
|
143
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
144
|
+
hash1 = hash(fos)
|
|
145
|
+
hash2 = hash(fos)
|
|
146
|
+
hash3 = hash(fos)
|
|
147
|
+
|
|
148
|
+
assert hash1 == hash2
|
|
149
|
+
assert hash2 == hash3
|
|
150
|
+
|
|
151
|
+
def test_immutability(self):
|
|
152
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
153
|
+
|
|
154
|
+
assert not hasattr(fos, "add")
|
|
155
|
+
assert not hasattr(fos, "remove")
|
|
156
|
+
assert not hasattr(fos, "discard")
|
|
157
|
+
assert not hasattr(fos, "pop")
|
|
158
|
+
assert not hasattr(fos, "clear")
|
|
159
|
+
assert not hasattr(fos, "update")
|
|
160
|
+
|
|
161
|
+
def test_set_operations_type_compatibility(self):
|
|
162
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
163
|
+
|
|
164
|
+
assert isinstance(fos, Iterable)
|
|
165
|
+
|
|
166
|
+
def test_with_unhashable_types(self):
|
|
167
|
+
with pytest.raises(TypeError):
|
|
168
|
+
FrozenOrderedSet([[1, 2], [3, 4]])
|
|
169
|
+
|
|
170
|
+
with pytest.raises(TypeError):
|
|
171
|
+
FrozenOrderedSet([{1: 2}, {3: 4}])
|
|
172
|
+
|
|
173
|
+
def test_order_preservation_complex(self):
|
|
174
|
+
fos = FrozenOrderedSet([3, 1, 4, 1, 5, 9, 2, 6, 5])
|
|
175
|
+
expected_order = [3, 1, 4, 5, 9, 2, 6]
|
|
176
|
+
assert list(fos) == expected_order
|
|
177
|
+
|
|
178
|
+
def test_boolean_evaluation(self):
|
|
179
|
+
assert not FrozenOrderedSet()
|
|
180
|
+
assert FrozenOrderedSet([1])
|
|
181
|
+
assert FrozenOrderedSet([0])
|
|
182
|
+
assert FrozenOrderedSet([None])
|
|
183
|
+
|
|
184
|
+
def test_large_dataset(self):
|
|
185
|
+
large_list = list(range(1000))
|
|
186
|
+
fos = FrozenOrderedSet(large_list)
|
|
187
|
+
|
|
188
|
+
assert len(fos) == 1000
|
|
189
|
+
assert list(fos) == large_list
|
|
190
|
+
assert 500 in fos
|
|
191
|
+
assert 1000 not in fos
|
|
192
|
+
|
|
193
|
+
def test_nested_iteration(self):
|
|
194
|
+
fos = FrozenOrderedSet(["a", "b", "c"])
|
|
195
|
+
|
|
196
|
+
iter1 = iter(fos)
|
|
197
|
+
iter2 = iter(fos)
|
|
198
|
+
|
|
199
|
+
assert next(iter1) == "a"
|
|
200
|
+
assert next(iter2) == "a"
|
|
201
|
+
assert next(iter1) == "b"
|
|
202
|
+
assert next(iter2) == "b"
|
|
203
|
+
|
|
204
|
+
def test_edge_cases_empty_string_and_zero(self):
|
|
205
|
+
fos = FrozenOrderedSet(["", 0, False, None])
|
|
206
|
+
|
|
207
|
+
assert len(fos) == 3
|
|
208
|
+
assert "" in fos
|
|
209
|
+
assert 0 in fos
|
|
210
|
+
assert False in fos
|
|
211
|
+
assert None in fos
|
|
212
|
+
|
|
213
|
+
assert list(fos) == ["", 0, None]
|
|
214
|
+
|
|
215
|
+
def test_generator_as_input(self):
|
|
216
|
+
|
|
217
|
+
def gen():
|
|
218
|
+
yield 1
|
|
219
|
+
yield 2
|
|
220
|
+
yield 3
|
|
221
|
+
yield 2
|
|
222
|
+
|
|
223
|
+
fos = FrozenOrderedSet(gen())
|
|
224
|
+
assert list(fos) == [1, 2, 3]
|
|
225
|
+
assert len(fos) == 3
|
|
226
|
+
|
|
227
|
+
def test_comparison_with_different_types(self):
|
|
228
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
229
|
+
|
|
230
|
+
assert fos != "not_iterable_comparison"
|
|
231
|
+
assert fos == frozenset([3, 2, 1])
|
|
232
|
+
|
|
233
|
+
def test_index_access(self):
|
|
234
|
+
fos = FrozenOrderedSet([10, 20, 30, 40, 50])
|
|
235
|
+
|
|
236
|
+
assert fos[0] == 10
|
|
237
|
+
assert fos[1] == 20
|
|
238
|
+
assert fos[2] == 30
|
|
239
|
+
assert fos[3] == 40
|
|
240
|
+
assert fos[4] == 50
|
|
241
|
+
|
|
242
|
+
assert fos[-1] == 50
|
|
243
|
+
assert fos[-2] == 40
|
|
244
|
+
assert fos[-3] == 30
|
|
245
|
+
assert fos[-4] == 20
|
|
246
|
+
assert fos[-5] == 10
|
|
247
|
+
|
|
248
|
+
def test_index_access_empty_set(self):
|
|
249
|
+
fos = FrozenOrderedSet()
|
|
250
|
+
|
|
251
|
+
with pytest.raises(IndexError):
|
|
252
|
+
fos[0]
|
|
253
|
+
|
|
254
|
+
with pytest.raises(IndexError):
|
|
255
|
+
fos[-1]
|
|
256
|
+
|
|
257
|
+
def test_index_access_out_of_bounds(self):
|
|
258
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
259
|
+
|
|
260
|
+
with pytest.raises(IndexError):
|
|
261
|
+
fos[3]
|
|
262
|
+
|
|
263
|
+
with pytest.raises(IndexError):
|
|
264
|
+
fos[10]
|
|
265
|
+
|
|
266
|
+
with pytest.raises(IndexError):
|
|
267
|
+
fos[-4]
|
|
268
|
+
|
|
269
|
+
with pytest.raises(IndexError):
|
|
270
|
+
fos[-10]
|
|
271
|
+
|
|
272
|
+
def test_index_access_single_element(self):
|
|
273
|
+
fos = FrozenOrderedSet([42])
|
|
274
|
+
|
|
275
|
+
assert fos[0] == 42
|
|
276
|
+
assert fos[-1] == 42
|
|
277
|
+
|
|
278
|
+
with pytest.raises(IndexError):
|
|
279
|
+
fos[1]
|
|
280
|
+
|
|
281
|
+
with pytest.raises(IndexError):
|
|
282
|
+
fos[-2]
|
|
283
|
+
|
|
284
|
+
def test_index_access_with_strings(self):
|
|
285
|
+
fos = FrozenOrderedSet(["apple", "banana", "cherry"])
|
|
286
|
+
|
|
287
|
+
assert fos[0] == "apple"
|
|
288
|
+
assert fos[1] == "banana"
|
|
289
|
+
assert fos[2] == "cherry"
|
|
290
|
+
assert fos[-1] == "cherry"
|
|
291
|
+
assert fos[-2] == "banana"
|
|
292
|
+
assert fos[-3] == "apple"
|
|
293
|
+
|
|
294
|
+
def test_index_access_with_duplicates_removed(self):
|
|
295
|
+
fos = FrozenOrderedSet([5, 3, 5, 1, 3, 7])
|
|
296
|
+
|
|
297
|
+
assert fos[0] == 5
|
|
298
|
+
assert fos[1] == 3
|
|
299
|
+
assert fos[2] == 1
|
|
300
|
+
assert fos[3] == 7
|
|
301
|
+
|
|
302
|
+
with pytest.raises(IndexError):
|
|
303
|
+
fos[4]
|
|
304
|
+
|
|
305
|
+
def test_index_access_invalid_type(self):
|
|
306
|
+
fos = FrozenOrderedSet([1, 2, 3])
|
|
307
|
+
|
|
308
|
+
with pytest.raises(TypeError):
|
|
309
|
+
fos["invalid"] # type: ignore[assignment]
|
|
310
|
+
|
|
311
|
+
with pytest.raises(TypeError):
|
|
312
|
+
fos[1.5] # type: ignore[assignment]
|
|
313
|
+
|
|
314
|
+
with pytest.raises(TypeError):
|
|
315
|
+
fos[None] # type: ignore[assignment]
|
|
@@ -17,6 +17,37 @@ KNOWN_FAILURES = frozenset([
|
|
|
17
17
|
'arelle.archive.plugin.validate.XFsyntax.xf',
|
|
18
18
|
'arelle.formula.FormulaEvaluator',
|
|
19
19
|
])
|
|
20
|
+
|
|
21
|
+
# OIM Taxonomy uses typing features not available in Python 3.9 and earlier.
|
|
22
|
+
# Python 3.9 support will be dropped before this plugin is fully supported.
|
|
23
|
+
if sys.version_info < (3, 10):
|
|
24
|
+
KNOWN_FAILURES |= frozenset([
|
|
25
|
+
'arelle.plugin.OimTaxonomy.__init__',
|
|
26
|
+
'arelle.plugin.OimTaxonomy.ModelValueMore',
|
|
27
|
+
'arelle.plugin.OimTaxonomy.ValidateDTS',
|
|
28
|
+
'arelle.plugin.OimTaxonomy.ViewXbrlTxmyObj',
|
|
29
|
+
'arelle.plugin.OimTaxonomy.XbrlAbstract',
|
|
30
|
+
'arelle.plugin.OimTaxonomy.XbrlConcept',
|
|
31
|
+
'arelle.plugin.OimTaxonomy.XbrlConst',
|
|
32
|
+
'arelle.plugin.OimTaxonomy.XbrlCube',
|
|
33
|
+
'arelle.plugin.OimTaxonomy.XbrlDimension',
|
|
34
|
+
'arelle.plugin.OimTaxonomy.XbrlDts',
|
|
35
|
+
'arelle.plugin.OimTaxonomy.XbrlEntity',
|
|
36
|
+
'arelle.plugin.OimTaxonomy.XbrlGroup',
|
|
37
|
+
'arelle.plugin.OimTaxonomy.XbrlImportedTaxonomy',
|
|
38
|
+
'arelle.plugin.OimTaxonomy.XbrlLabel',
|
|
39
|
+
'arelle.plugin.OimTaxonomy.XbrlNetwork',
|
|
40
|
+
'arelle.plugin.OimTaxonomy.XbrlProperty',
|
|
41
|
+
'arelle.plugin.OimTaxonomy.XbrlReference',
|
|
42
|
+
'arelle.plugin.OimTaxonomy.XbrlReport',
|
|
43
|
+
'arelle.plugin.OimTaxonomy.XbrlTableTemplate',
|
|
44
|
+
'arelle.plugin.OimTaxonomy.XbrlTaxonomy',
|
|
45
|
+
'arelle.plugin.OimTaxonomy.XbrlTaxonomyObject',
|
|
46
|
+
'arelle.plugin.OimTaxonomy.XbrlTransform',
|
|
47
|
+
'arelle.plugin.OimTaxonomy.XbrlTypes',
|
|
48
|
+
'arelle.plugin.OimTaxonomy.XbrlUnit',
|
|
49
|
+
])
|
|
50
|
+
|
|
20
51
|
# Don't test common third party plugins which may be copied into a developer's workspace.
|
|
21
52
|
IGNORE_MODULE_PREFIXES = (
|
|
22
53
|
'arelle.plugin.EDGAR',
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from arelle.PythonUtil import OrderedSet
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestOrderedSet:
|
|
8
|
+
|
|
9
|
+
def test_init_empty(self):
|
|
10
|
+
os = OrderedSet()
|
|
11
|
+
assert len(os) == 0
|
|
12
|
+
assert list(os) == []
|
|
13
|
+
assert bool(os) is False
|
|
14
|
+
|
|
15
|
+
def test_init_with_iterable(self):
|
|
16
|
+
os = OrderedSet([1, 2, 3, 2, 1])
|
|
17
|
+
assert len(os) == 3
|
|
18
|
+
assert list(os) == [1, 2, 3]
|
|
19
|
+
|
|
20
|
+
def test_add_duplicate_order(self):
|
|
21
|
+
os = OrderedSet()
|
|
22
|
+
os.add(1)
|
|
23
|
+
os.add(2)
|
|
24
|
+
os.add(1)
|
|
25
|
+
assert list(os) == [1, 2]
|
|
26
|
+
assert len(os) == 2
|
|
27
|
+
|
|
28
|
+
def test_contains(self):
|
|
29
|
+
os = OrderedSet([1, 2, 3])
|
|
30
|
+
assert 1 in os
|
|
31
|
+
assert 2 in os
|
|
32
|
+
assert 3 in os
|
|
33
|
+
assert 4 not in os
|
|
34
|
+
assert "1" not in os
|
|
35
|
+
|
|
36
|
+
def test_update(self):
|
|
37
|
+
os = OrderedSet([1, 2])
|
|
38
|
+
os.update([3, 4, 2, 5])
|
|
39
|
+
assert list(os) == [1, 2, 3, 4, 5]
|
|
40
|
+
|
|
41
|
+
def test_update_with_string(self):
|
|
42
|
+
os = OrderedSet(['a', 'b'])
|
|
43
|
+
os.update("bcd")
|
|
44
|
+
assert list(os) == ['a', 'b', 'c', 'd']
|
|
45
|
+
|
|
46
|
+
def test_discard(self):
|
|
47
|
+
os = OrderedSet([1, 2, 3, 4])
|
|
48
|
+
os.discard(2)
|
|
49
|
+
assert list(os) == [1, 3, 4]
|
|
50
|
+
|
|
51
|
+
# Discarding non-existent element should not raise error
|
|
52
|
+
non_existent_element = 10
|
|
53
|
+
os.discard(non_existent_element)
|
|
54
|
+
assert list(os) == [1, 3, 4]
|
|
55
|
+
|
|
56
|
+
def test_discard_from_empty(self):
|
|
57
|
+
os = OrderedSet()
|
|
58
|
+
os.discard(1)
|
|
59
|
+
assert len(os) == 0
|
|
60
|
+
|
|
61
|
+
def test_pop_last(self):
|
|
62
|
+
os = OrderedSet([1, 2, 3, 4])
|
|
63
|
+
result = os.pop()
|
|
64
|
+
assert result == 4
|
|
65
|
+
assert list(os) == [1, 2, 3]
|
|
66
|
+
|
|
67
|
+
def test_pop_first(self):
|
|
68
|
+
os = OrderedSet([1, 2, 3, 4])
|
|
69
|
+
result = os.pop(last=False)
|
|
70
|
+
assert result == 1
|
|
71
|
+
assert list(os) == [2, 3, 4]
|
|
72
|
+
|
|
73
|
+
def test_pop_empty_set(self):
|
|
74
|
+
os = OrderedSet()
|
|
75
|
+
with pytest.raises(KeyError, match="set is empty"):
|
|
76
|
+
os.pop()
|
|
77
|
+
|
|
78
|
+
def test_iteration(self):
|
|
79
|
+
os = OrderedSet([1, 2, 3])
|
|
80
|
+
result = []
|
|
81
|
+
for item in os:
|
|
82
|
+
result.append(item)
|
|
83
|
+
assert result == [1, 2, 3]
|
|
84
|
+
|
|
85
|
+
def test_reversed_iteration(self):
|
|
86
|
+
os = OrderedSet([1, 2, 3])
|
|
87
|
+
result = list(reversed(os))
|
|
88
|
+
assert result == [3, 2, 1]
|
|
89
|
+
|
|
90
|
+
def test_len(self):
|
|
91
|
+
os = OrderedSet()
|
|
92
|
+
assert len(os) == 0
|
|
93
|
+
|
|
94
|
+
os.add(1)
|
|
95
|
+
assert len(os) == 1
|
|
96
|
+
|
|
97
|
+
os.add(2)
|
|
98
|
+
assert len(os) == 2
|
|
99
|
+
|
|
100
|
+
os.add(1) # Duplicate
|
|
101
|
+
assert len(os) == 2
|
|
102
|
+
|
|
103
|
+
def test_bool(self):
|
|
104
|
+
os = OrderedSet()
|
|
105
|
+
assert bool(os) is False
|
|
106
|
+
|
|
107
|
+
os.add(1)
|
|
108
|
+
assert bool(os) is True
|
|
109
|
+
|
|
110
|
+
def test_repr_empty(self):
|
|
111
|
+
os = OrderedSet()
|
|
112
|
+
assert repr(os) == "OrderedSet()"
|
|
113
|
+
|
|
114
|
+
def test_repr_with_elements(self):
|
|
115
|
+
os = OrderedSet([1, 2, 3])
|
|
116
|
+
assert repr(os) == "OrderedSet([1, 2, 3])"
|
|
117
|
+
|
|
118
|
+
def test_eq_with_ordered_set(self):
|
|
119
|
+
os1 = OrderedSet([1, 2, 3])
|
|
120
|
+
os2 = OrderedSet([1, 2, 3])
|
|
121
|
+
os3 = OrderedSet([3, 2, 1])
|
|
122
|
+
os4 = OrderedSet([1, 2])
|
|
123
|
+
|
|
124
|
+
assert os1 == os2
|
|
125
|
+
assert os1 != os3
|
|
126
|
+
assert os1 != os4
|
|
127
|
+
|
|
128
|
+
def test_eq_with_regular_set(self):
|
|
129
|
+
os = OrderedSet([1, 2, 3])
|
|
130
|
+
s = {1, 2, 3}
|
|
131
|
+
s_different = {1, 2}
|
|
132
|
+
|
|
133
|
+
assert os == s
|
|
134
|
+
assert os != s_different
|
|
135
|
+
|
|
136
|
+
def test_eq_with_list(self):
|
|
137
|
+
os = OrderedSet([1, 2, 3])
|
|
138
|
+
lst = [1, 2, 3]
|
|
139
|
+
|
|
140
|
+
assert os == lst
|
|
141
|
+
|
|
142
|
+
def test_eq_with_non_iterable(self):
|
|
143
|
+
os = OrderedSet([1, 2, 3])
|
|
144
|
+
assert os != 42
|
|
145
|
+
assert os != "hello"
|
|
146
|
+
|
|
147
|
+
def test_order_preservation(self):
|
|
148
|
+
os = OrderedSet()
|
|
149
|
+
items = [5, 1, 3, 2, 4]
|
|
150
|
+
for item in items:
|
|
151
|
+
os.add(item)
|
|
152
|
+
assert list(os) == items
|
|
153
|
+
|
|
154
|
+
def test_order_preservation_with_duplicates(self):
|
|
155
|
+
os = OrderedSet()
|
|
156
|
+
os.add(1)
|
|
157
|
+
os.add(2)
|
|
158
|
+
os.add(3)
|
|
159
|
+
os.add(2)
|
|
160
|
+
assert list(os) == [1, 2, 3]
|
|
161
|
+
|
|
162
|
+
def test_complex_operations(self):
|
|
163
|
+
os = OrderedSet([1, 2, 3, 4, 5])
|
|
164
|
+
|
|
165
|
+
os.discard(3)
|
|
166
|
+
os.discard(5)
|
|
167
|
+
assert list(os) == [1, 2, 4]
|
|
168
|
+
|
|
169
|
+
os.add(6)
|
|
170
|
+
os.add(0)
|
|
171
|
+
assert list(os) == [1, 2, 4, 6, 0]
|
|
172
|
+
|
|
173
|
+
os.update([7, 2, 8])
|
|
174
|
+
assert list(os) == [1, 2, 4, 6, 0, 7, 8]
|
|
175
|
+
|
|
176
|
+
last = os.pop()
|
|
177
|
+
first = os.pop(last=False)
|
|
178
|
+
assert last == 8
|
|
179
|
+
assert first == 1
|
|
180
|
+
assert list(os) == [2, 4, 6, 0, 7]
|
|
181
|
+
|
|
182
|
+
def test_empty_set_operations(self):
|
|
183
|
+
os = OrderedSet()
|
|
184
|
+
|
|
185
|
+
assert list(os) == []
|
|
186
|
+
assert list(reversed(os)) == []
|
|
187
|
+
|
|
188
|
+
os.update([])
|
|
189
|
+
assert len(os) == 0
|
|
190
|
+
|
|
191
|
+
def test_single_element_operations(self):
|
|
192
|
+
os = OrderedSet([42])
|
|
193
|
+
|
|
194
|
+
assert len(os) == 1
|
|
195
|
+
assert 42 in os
|
|
196
|
+
assert list(os) == [42]
|
|
197
|
+
assert list(reversed(os)) == [42]
|
|
198
|
+
|
|
199
|
+
result = os.pop()
|
|
200
|
+
assert result == 42
|
|
201
|
+
assert len(os) == 0
|
|
202
|
+
|
|
203
|
+
def test_unhashable_types_not_supported(self):
|
|
204
|
+
os = OrderedSet()
|
|
205
|
+
with pytest.raises(TypeError):
|
|
206
|
+
os.add([1, 2, 3])
|
|
207
|
+
|
|
208
|
+
with pytest.raises(TypeError):
|
|
209
|
+
os.add({1: 2})
|
|
210
|
+
|
|
211
|
+
def test_index_access_basic(self):
|
|
212
|
+
os = OrderedSet([1, 2, 3, 4, 5])
|
|
213
|
+
|
|
214
|
+
assert os[0] == 1
|
|
215
|
+
assert os[1] == 2
|
|
216
|
+
assert os[2] == 3
|
|
217
|
+
assert os[3] == 4
|
|
218
|
+
assert os[4] == 5
|
|
219
|
+
|
|
220
|
+
assert os[-1] == 5
|
|
221
|
+
assert os[-2] == 4
|
|
222
|
+
assert os[-3] == 3
|
|
223
|
+
assert os[-4] == 2
|
|
224
|
+
assert os[-5] == 1
|
|
225
|
+
|
|
226
|
+
def test_index_access_out_of_bounds(self):
|
|
227
|
+
os = OrderedSet([1, 2, 3])
|
|
228
|
+
|
|
229
|
+
with pytest.raises(IndexError):
|
|
230
|
+
os[3]
|
|
231
|
+
with pytest.raises(IndexError):
|
|
232
|
+
os[10]
|
|
233
|
+
|
|
234
|
+
with pytest.raises(IndexError):
|
|
235
|
+
os[-4]
|
|
236
|
+
with pytest.raises(IndexError):
|
|
237
|
+
os[-10]
|
|
238
|
+
|
|
239
|
+
def test_index_access_empty_set(self):
|
|
240
|
+
os = OrderedSet()
|
|
241
|
+
|
|
242
|
+
with pytest.raises(IndexError):
|
|
243
|
+
os[0]
|
|
244
|
+
with pytest.raises(IndexError):
|
|
245
|
+
os[-1]
|
|
246
|
+
|
|
247
|
+
def test_index_access_single_element(self):
|
|
248
|
+
os = OrderedSet([42])
|
|
249
|
+
|
|
250
|
+
assert os[0] == 42
|
|
251
|
+
assert os[-1] == 42
|
|
252
|
+
|
|
253
|
+
with pytest.raises(IndexError):
|
|
254
|
+
os[1]
|
|
255
|
+
with pytest.raises(IndexError):
|
|
256
|
+
os[-2]
|
|
257
|
+
|
|
258
|
+
def test_index_access_after_modifications(self):
|
|
259
|
+
os = OrderedSet([1, 2, 3, 4])
|
|
260
|
+
|
|
261
|
+
os.discard(2)
|
|
262
|
+
assert os[0] == 1
|
|
263
|
+
assert os[1] == 3
|
|
264
|
+
assert os[2] == 4
|
|
265
|
+
|
|
266
|
+
os.add(5)
|
|
267
|
+
assert os[3] == 5
|
|
268
|
+
|
|
269
|
+
os.pop()
|
|
270
|
+
assert len(os) == 3
|
|
271
|
+
with pytest.raises(IndexError):
|
|
272
|
+
os[3]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|