diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a491f84b89cf355eef3a15a554f6ef68ab1f28..e9be3af5e8af94fdae3047da28ca16a191387d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ -# v2.24.0 +# v2.23.1 -* completely overhauled [overload](https://satella.readthedocs.io/en/latest/coding/functions.html#function-overloading), - ie. fixed #57. +* added OnStrOnlyName + +[//]: # (* completely overhauled [overload](https://satella.readthedocs.io/en/latest/coding/functions.html#function-overloading), ) + +[//]: # ( ie. fixed #57.) diff --git a/docs/coding/structures.rst b/docs/coding/structures.rst index 0cf7a60e782828c7c7ae9427d1cab46e9f9af031..b1e94aa1296f021d96568ec3c31326f0ec1f0415 100644 --- a/docs/coding/structures.rst +++ b/docs/coding/structures.rst @@ -95,6 +95,12 @@ Mixins are classes whose constructor you do not need to invoke. They magically endow your class with chosen properties, often by overloading their specific special methods. +OnStrOnlyName +------------- + +.. autoclass:: satella.coding.structures.OnStrOnlyName + :members: + HashableMixin ------------- diff --git a/satella/__init__.py b/satella/__init__.py index 1c24e3331d9c331f3786944f0d8c003c36aa6c6a..6b8976459efe6be291bd4e6dff8fe1f91642a234 100644 --- a/satella/__init__.py +++ b/satella/__init__.py @@ -1 +1 @@ -__version__ = '2.23.1b1' +__version__ = '2.23.1' diff --git a/satella/coding/structures/__init__.py b/satella/coding/structures/__init__.py index 9677096d43acfc65c9268f8c30b5047c67c8f1d3..15abee15ade56975219ab6caafd0cdcccce5299c 100644 --- a/satella/coding/structures/__init__.py +++ b/satella/coding/structures/__init__.py @@ -6,7 +6,7 @@ from .heaps import Heap, SetHeap, TimeBasedHeap, TimeBasedSetHeap from .immutable import Immutable, frozendict, NotEqualToAnything, NOT_EQUAL_TO_ANYTHING from .mixins import OmniHashableMixin, ReprableMixin, StrEqHashableMixin, ComparableIntEnum, \ HashableIntEnum, ComparableAndHashableBy, ComparableAndHashableByInt, ComparableEnum, \ - HashableMixin, ComparableAndHashableByStr, DictionaryEQAble + HashableMixin, ComparableAndHashableByStr, DictionaryEQAble, OnStrOnlyName from .proxy import Proxy from .queues import Subqueue from .ranking import Ranking @@ -22,7 +22,7 @@ from .zip_dict import SetZip from .push_iterable import PushIterable __all__ = [ - 'PushIterable', + 'PushIterable', 'OnStrOnlyName', 'Vector', 'SetZip', 'DBStorage', 'SyncableDroppable', 'LRU', diff --git a/satella/coding/structures/mixins/__init__.py b/satella/coding/structures/mixins/__init__.py index 948d863102e452b3f9ba3c5ea8cf807423e2cbfa..94121dc4f95c0f11e6050a4d09eccf876dc84094 100644 --- a/satella/coding/structures/mixins/__init__.py +++ b/satella/coding/structures/mixins/__init__.py @@ -1,4 +1,4 @@ -from .enums import ComparableEnum, ComparableIntEnum, HashableIntEnum +from .enums import ComparableEnum, ComparableIntEnum, HashableIntEnum, OnStrOnlyName from .hashable import ComparableAndHashableBy, ComparableAndHashableByInt, \ OmniHashableMixin, HashableMixin, ComparableAndHashableByStr from .strings import ReprableMixin, StrEqHashableMixin @@ -7,4 +7,4 @@ from .eqable import DictionaryEQAble __all__ = ['ComparableIntEnum', 'ComparableEnum', 'ComparableAndHashableBy', 'HashableIntEnum', 'ComparableAndHashableByInt', 'OmniHashableMixin', 'ReprableMixin', 'StrEqHashableMixin', 'HashableMixin', - 'ComparableAndHashableByStr', 'DictionaryEQAble'] + 'ComparableAndHashableByStr', 'DictionaryEQAble', 'OnStrOnlyName'] diff --git a/satella/coding/structures/mixins/enums.py b/satella/coding/structures/mixins/enums.py index 7dd5f95f64b411d8e3cff504ada7be5eeb1ac96d..4ebe734ec66980d21a4f86090dab1e605d1159c1 100644 --- a/satella/coding/structures/mixins/enums.py +++ b/satella/coding/structures/mixins/enums.py @@ -87,3 +87,23 @@ class ComparableIntEnum(HashableIntEnum): if isinstance(other, (int, float)): return self.value == other return self.value == int(other) + + +class OnStrOnlyName: + """ + A mix-in to add the following functionality to your class. + + tl;dr - the name will be used instead of ClassName.name. + + >>> from enum import Enum + >>> class MyEnum(OnStrOnlyName, Enum): + >>> A = 0 + >>> B = 1 + >>> C = 'test' + >>> assert str(MyEnum.A) == 'A' + >>> assert str(MyEnum.B) == 'B' + >>> assert str(MyEnum.C) == 'test' + """ + + def __str__(self) -> str: + return self.name diff --git a/tests/test_coding/test_structures.py b/tests/test_coding/test_structures.py index 9acf9550ec0c588a56d2356e0a388c3e206c048e..878a76babb84951ecad79dfb938718750d3cf2ee 100644 --- a/tests/test_coding/test_structures.py +++ b/tests/test_coding/test_structures.py @@ -4,7 +4,7 @@ import copy import math import time import unittest - +from enum import Enum from unittest import mock from satella.coding.concurrent import call_in_separate_thread @@ -15,11 +15,39 @@ from satella.coding.structures import TimeBasedHeap, Heap, typednamedtuple, \ CacheDict, StrEqHashableMixin, ComparableIntEnum, HashableIntEnum, ComparableAndHashableBy, \ ComparableAndHashableByInt, SparseMatrix, ExclusiveWritebackCache, Subqueue, \ CountingDict, ComparableEnum, LRU, LRUCacheDict, Vector, DefaultDict, PushIterable, \ - ComparableAndHashableByStr, NotEqualToAnything, NOT_EQUAL_TO_ANYTHING, DictionaryEQAble, SetZip + ComparableAndHashableByStr, NotEqualToAnything, NOT_EQUAL_TO_ANYTHING, DictionaryEQAble, SetZip, OnStrOnlyName + + +def continue_testing_omni(self, omni_class): + e1 = omni_class(2) + e2 = omni_class(1) + e3 = omni_class(1) + + self.assertEqual(e2, e3) + self.assertNotEqual(e1, e2) + self.assertNotEqual(e1, e3) + + a = { + e1: '1', e2: '2', e3: '3' + } + + self.assertEqual(a[e1], '1') + self.assertEqual(hash(e1), hash(2)) class TestStructures(unittest.TestCase): + def test_onstronlyname(self): + + class MyEnum(OnStrOnlyName, Enum): + A = 0 + B = 1 + C = 'test' + + self.assertEqual(str(MyEnum.A), 'A') + self.assertEqual(str(MyEnum.B), 'B') + self.assertEqual(str(MyEnum.C), 'C') + def test_zip(self): a = set([1,2, 3]) b = set([3,4,5]) @@ -694,22 +722,6 @@ class TestStructures(unittest.TestCase): self.assertEqual(hash(a), hash(b)) self.assertRaises(TypeError, lambda: a.update({3: 5})) - def continue_testing_omni(self, Omni): - e1 = Omni(2) - e2 = Omni(1) - e3 = Omni(1) - - self.assertEqual(e2, e3) - self.assertNotEqual(e1, e2) - self.assertNotEqual(e1, e3) - - a = { - e1: '1', e2: '2', e3: '3' - } - - self.assertEqual(a[e1], '1') - self.assertEqual(hash(e1), hash(2)) - def test_omni_not_filled_in_fields(self): class Omni1(OmniHashableMixin): _HASH_FIELDS_TO_USE = 'a' @@ -744,7 +756,7 @@ class TestStructures(unittest.TestCase): def __init__(self, a): self.a = a - self.continue_testing_omni(Omni) + continue_testing_omni(self, Omni) def test_omni(self): class Omni(OmniHashableMixin): @@ -752,7 +764,7 @@ class TestStructures(unittest.TestCase): def __init__(self, a): self.a = a - self.continue_testing_omni(Omni) + continue_testing_omni(self, Omni) def test_tbsh(self): tbh = TimeBasedSetHeap()