cmp3 0.6.2__py3-none-any.whl → 0.6.4__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.
cmp3/core/__init__.py CHANGED
@@ -11,14 +11,22 @@ def cmp(x: Any, y: Any, /, *, mode: str = "portingguide") -> float | int:
11
11
  if mode == "portingguide":
12
12
  return (x > y) - (x < y)
13
13
  if mode == "poset":
14
- if (x <= y) and (y <= x):
14
+ return cmp_poset(x, y)
15
+ raise ValueError("%r is not an appropriate value for mode." % mode)
16
+
17
+
18
+ def cmp_poset(x: Any, y: Any, /) -> float | int:
19
+ "This function returns a value that compares to 0 as x compares to y under the assumption that both arguments belong to a poset."
20
+ if x <= y:
21
+ if y <= x:
15
22
  return 0
16
- if (x <= y) and (not y <= x):
23
+ else:
17
24
  return -1
18
- if (not x <= y) and (y <= x):
25
+ else:
26
+ if y <= x:
19
27
  return 1
20
- return float("nan")
21
- raise ValueError
28
+ else:
29
+ return float("nan")
22
30
 
23
31
 
24
32
  def cmpDeco(cls: type, /) -> type:
cmp3/tests/test_all.py ADDED
@@ -0,0 +1,113 @@
1
+ import math
2
+ import unittest
3
+ from typing import *
4
+
5
+ from cmp3.core import CmpABC, cmp, cmp_poset, cmpDeco
6
+
7
+
8
+ class TestCmpFunction(unittest.TestCase):
9
+ def test_portingguide_less(self: Self) -> None:
10
+ self.assertEqual(cmp(1, 2), -1)
11
+ self.assertEqual(cmp(-5, -1), -1)
12
+
13
+ def test_portingguide_equal(self: Self) -> None:
14
+ self.assertEqual(cmp(3, 3), 0)
15
+ self.assertEqual(cmp("a", "a"), 0)
16
+
17
+ def test_portingguide_greater(self: Self) -> None:
18
+ self.assertEqual(cmp(2, 1), 1)
19
+ self.assertEqual(cmp("b", "a"), 1)
20
+
21
+ def test_poset_mode_uses_poset_semantics(self: Self) -> None:
22
+ # For totally ordered ints, this should behave like normal cmp
23
+ self.assertEqual(cmp(1, 2, mode="poset"), -1)
24
+ self.assertEqual(cmp(2, 1, mode="poset"), 1)
25
+ self.assertEqual(cmp(5, 5, mode="poset"), 0)
26
+
27
+ def test_invalid_mode_raises(self: Self) -> None:
28
+ with self.assertRaises(ValueError):
29
+ cmp(1, 2, mode="something-else")
30
+
31
+
32
+ class TestCmpPoset(unittest.TestCase):
33
+ def test_total_order_ints(self: Self) -> None:
34
+ self.assertEqual(cmp_poset(1, 2), -1)
35
+ self.assertEqual(cmp_poset(2, 1), 1)
36
+ self.assertEqual(cmp_poset(3, 3), 0)
37
+
38
+ def test_incomparable_returns_nan(self: Self) -> None:
39
+ class Incomparable:
40
+ def __le__(self: Self, other: Any) -> bool:
41
+ # Always False, so no order relation is established
42
+ return False
43
+
44
+ result: Any
45
+ x: Incomparable
46
+ y: Incomparable
47
+
48
+ x = Incomparable()
49
+ y = Incomparable()
50
+ result = cmp_poset(x, y)
51
+ self.assertTrue(math.isnan(result))
52
+
53
+
54
+ # A concrete implementation of CmpABC for testing
55
+ class Box(CmpABC):
56
+ def __init__(self: Self, value: Any) -> None:
57
+ self.value = value
58
+
59
+ def __cmp__(self: Self, other: Any) -> Any:
60
+ if not isinstance(other, Box):
61
+ return NotImplemented
62
+ return (self.value > other.value) - (self.value < other.value)
63
+
64
+
65
+ @cmpDeco
66
+ class DecoratedBox:
67
+ def __init__(self: Self, value: Any) -> None:
68
+ self.value = value
69
+
70
+ def __cmp__(self: Self, other: Any) -> Any:
71
+ if not isinstance(other, DecoratedBox):
72
+ return NotImplemented
73
+ return (self.value > other.value) - (self.value < other.value)
74
+
75
+
76
+ class TestCmpABCAndDeco(unittest.TestCase):
77
+ def test_cmpabc_is_abstract(self: Self) -> None:
78
+ with self.assertRaises(TypeError):
79
+ CmpABC() # type: ignore[abstract] # must not be instantiable
80
+
81
+ def test_cmpabc_comparisons(self: Self) -> None:
82
+ a: Box
83
+ b: Box
84
+ c: Box
85
+ a = Box(1)
86
+ b = Box(2)
87
+ c = Box(1)
88
+
89
+ self.assertTrue(a < b)
90
+ self.assertTrue(a <= b)
91
+ self.assertTrue(b > a)
92
+ self.assertTrue(b >= a)
93
+ self.assertTrue(a == c)
94
+ self.assertTrue(a != b)
95
+
96
+ def test_cmpdeco_on_regular_class(self: Self) -> None:
97
+ x: DecoratedBox
98
+ y: DecoratedBox
99
+ z: DecoratedBox
100
+ x = DecoratedBox(10)
101
+ y = DecoratedBox(20)
102
+ z = DecoratedBox(10)
103
+
104
+ self.assertTrue(x < y)
105
+ self.assertTrue(x <= y)
106
+ self.assertTrue(y > x)
107
+ self.assertTrue(y >= x)
108
+ self.assertTrue(x == z)
109
+ self.assertTrue(x != y)
110
+
111
+
112
+ if __name__ == "__main__":
113
+ unittest.main()
@@ -0,0 +1,119 @@
1
+ import math
2
+ import unittest
3
+ from typing import *
4
+
5
+ from cmp3 import core
6
+
7
+
8
+ class TestCmpPortingGuide(unittest.TestCase):
9
+ def test_equal(self: Self) -> None:
10
+ self.assertEqual(core.cmp(1, 1), 0)
11
+ self.assertEqual(core.cmp("a", "a"), 0)
12
+
13
+ def test_less(self: Self) -> None:
14
+ self.assertEqual(core.cmp(1, 2), -1)
15
+ self.assertEqual(core.cmp("a", "b"), -1)
16
+
17
+ def test_greater(self: Self) -> None:
18
+ self.assertEqual(core.cmp(2, 1), 1)
19
+ self.assertEqual(core.cmp("b", "a"), 1)
20
+
21
+ def test_invalid_mode_raises(self: Self) -> None:
22
+ with self.assertRaises(ValueError):
23
+ core.cmp(1, 2, mode="invalid-mode")
24
+
25
+
26
+ class TestCmpPoset(unittest.TestCase):
27
+ def test_poset_equal(self: Self) -> None:
28
+ # subset ordering: same set
29
+ self.assertEqual(core.cmp_poset({1, 2}, {1, 2}), 0)
30
+
31
+ def test_poset_less(self: Self) -> None:
32
+ # subset ordering: strict subset
33
+ self.assertEqual(core.cmp_poset({1}, {1, 2}), -1)
34
+
35
+ def test_poset_greater(self: Self) -> None:
36
+ # subset ordering: strict superset
37
+ self.assertEqual(core.cmp_poset({1, 2}, {1}), 1)
38
+
39
+ def test_poset_incomparable(self: Self) -> None:
40
+ # incomparable in subset ordering
41
+ res: Any
42
+ res = core.cmp_poset({1}, {2})
43
+ self.assertTrue(math.isnan(res))
44
+
45
+
46
+ class TestCmpModePoset(unittest.TestCase):
47
+ def test_cmp_uses_poset_mode(self: Self) -> None:
48
+ self.assertEqual(core.cmp({1}, {1, 2}, mode="poset"), -1)
49
+ self.assertEqual(core.cmp({1, 2}, {1}, mode="poset"), 1)
50
+ self.assertTrue(math.isnan(core.cmp({1}, {2}, mode="poset")))
51
+
52
+
53
+ class Number(core.CmpABC):
54
+ def __init__(self: Self, value: int) -> None:
55
+ self.value = value
56
+
57
+ def __cmp__(self: Self, other: Any) -> Any:
58
+ if not isinstance(other, Number):
59
+ return NotImplemented
60
+ # classic 3-way comparison
61
+ return (self.value > other.value) - (self.value < other.value)
62
+
63
+
64
+ class TestCmpDecoAndCmpABC(unittest.TestCase):
65
+ def setUp(self: Self) -> None:
66
+ self.a = Number(1)
67
+ self.b = Number(2)
68
+ self.c = Number(1)
69
+
70
+ def test_eq_ne(self: Self) -> None:
71
+ self.assertTrue(self.a == self.c)
72
+ self.assertFalse(self.a == self.b)
73
+ self.assertTrue(self.a != self.b)
74
+ self.assertFalse(self.a != self.c)
75
+
76
+ def test_lt_le(self: Self) -> None:
77
+ self.assertTrue(self.a < self.b)
78
+ self.assertTrue(self.a <= self.b)
79
+ self.assertTrue(self.a <= self.c)
80
+ self.assertFalse(self.b < self.a)
81
+
82
+ def test_gt_ge(self: Self) -> None:
83
+ self.assertTrue(self.b > self.a)
84
+ self.assertTrue(self.b >= self.a)
85
+ self.assertTrue(self.b >= self.c)
86
+ self.assertFalse(self.a > self.b)
87
+
88
+ def test_cmpabc_is_abstract(self: Self) -> None:
89
+ with self.assertRaises(TypeError):
90
+ core.CmpABC() # abstract, cannot be instantiated
91
+
92
+
93
+ class TestCmpDecoOnPlainClass(unittest.TestCase):
94
+ def test_decorator_on_non_abc_class(self: Self) -> None:
95
+ @core.cmpDeco
96
+ class Plain:
97
+ def __init__(self: Self, x: int) -> None:
98
+ self.x = x
99
+
100
+ def __cmp__(self: Self, other: Any) -> Any:
101
+ if not isinstance(other, Plain):
102
+ return NotImplemented
103
+ return (self.x > other.x) - (self.x < other.x)
104
+
105
+ p1: Plain
106
+ p2: Plain
107
+ p3: Plain
108
+ p1 = Plain(1)
109
+ p2 = Plain(2)
110
+ p3 = Plain(1)
111
+
112
+ self.assertTrue(p1 < p2)
113
+ self.assertTrue(p2 > p1)
114
+ self.assertTrue(p1 == p3)
115
+ self.assertTrue(p1 != p2)
116
+
117
+
118
+ if __name__ == "__main__":
119
+ unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmp3
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: This project updates the concept of __cmp__ for python3.
5
5
  Author-email: Johannes <johannes.programming@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -0,0 +1,10 @@
1
+ cmp3/__init__.py,sha256=hxvwX8wZhft-DkMAoU3xz65RMZib8nPQQiAbxba27iQ,49
2
+ cmp3/core/__init__.py,sha256=_xdO8zsRzwDegppawfT3zohm6xSHt5KC7C9jELqRYXQ,2199
3
+ cmp3/tests/__init__.py,sha256=HqmxhnTFFqh9Nzl7STV5GeDYqDmhrc9e1TCHssUbC1s,426
4
+ cmp3/tests/test_all.py,sha256=_RYEUhy3V7NjIZaA7JT2916lnXyIi6Xh1RY9dv4rD30,3342
5
+ cmp3/tests/test_core.py,sha256=SygGk85rzFlq5dQ0S6ht7w3DwL3y9oPcVCNf0XxkwH0,3679
6
+ cmp3-0.6.4.dist-info/licenses/LICENSE.txt,sha256=Jb9jm2E2hEO2LqnWwHeHt4cneyCbnZ1SBte0bgb9qoY,1074
7
+ cmp3-0.6.4.dist-info/METADATA,sha256=Ukb66EeYszwm68_kGx02cOlw5lN6co7G_RlglxCXJqs,2300
8
+ cmp3-0.6.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
9
+ cmp3-0.6.4.dist-info/top_level.txt,sha256=FzJWsf0Xj_eeRJuFle30ZFjVZs8ahy7oLhYdWx8YkgA,5
10
+ cmp3-0.6.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
cmp3/tests/test_1984.py DELETED
@@ -1,11 +0,0 @@
1
- import unittest
2
- from typing import *
3
-
4
-
5
- class Test1984(unittest.TestCase):
6
- def test_1984(self: Self) -> None:
7
- self.assertEqual(2 + 2, 4, "Ignorance is Strength")
8
-
9
-
10
- if __name__ == "__main__":
11
- unittest.main()
@@ -1,9 +0,0 @@
1
- cmp3/__init__.py,sha256=hxvwX8wZhft-DkMAoU3xz65RMZib8nPQQiAbxba27iQ,49
2
- cmp3/core/__init__.py,sha256=6uXJPePzO0rZVCYASVP2A3FU05F_87g1eTfkNdfOFCE,1947
3
- cmp3/tests/__init__.py,sha256=HqmxhnTFFqh9Nzl7STV5GeDYqDmhrc9e1TCHssUbC1s,426
4
- cmp3/tests/test_1984.py,sha256=_ami0cAP8vU0C8RpQhP1tLWnLFGTaeHlOG5O60RVKv8,222
5
- cmp3-0.6.2.dist-info/licenses/LICENSE.txt,sha256=Jb9jm2E2hEO2LqnWwHeHt4cneyCbnZ1SBte0bgb9qoY,1074
6
- cmp3-0.6.2.dist-info/METADATA,sha256=yUjZmwuPzD3MxbaB-8JgtyuXXXq-JJFIww7LKaO-cqI,2300
7
- cmp3-0.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- cmp3-0.6.2.dist-info/top_level.txt,sha256=FzJWsf0Xj_eeRJuFle30ZFjVZs8ahy7oLhYdWx8YkgA,5
9
- cmp3-0.6.2.dist-info/RECORD,,