diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1c60d8693072fa622e70c340a2002f8202aa5940..393cba875b39464976830e746f347d4d25de2701 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,15 +4,5 @@ build: tools: python: "3.9" -# Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py - # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs - # builder: "dirhtml" - # Fail on all warnings to avoid broken references - # fail_on_warning: true - - -python: - install: - - requirements: requirements.txt diff --git a/LICENSE b/LICENSE index 38e365b62b7a8efb3fef9c976833dbb420fd9132..3c7d6e54e6599d1311de31df1ce0fcacacede6a1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2013-2023 Piotr MaĹlanka +Copyright (c) 2013-2024 Piotr MaĹlanka Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/satella/coding/structures/dictionaries/objects.py b/satella/coding/structures/dictionaries/objects.py index b34493a52fa785e529392ed2230e7f7ac370a48b..cfbe5029f66e4316514dee0ff7d1a48d57624a18 100644 --- a/satella/coding/structures/dictionaries/objects.py +++ b/satella/coding/structures/dictionaries/objects.py @@ -1,3 +1,4 @@ +from __future__ import annotations import copy import typing as tp import warnings @@ -97,17 +98,16 @@ class KeyAwareDefaultDict(tp.MutableMapping[K, V]): self.dict = dict(*args, **kwargs) self.factory_function = factory_function - def __getitem__(self, item) -> V: + def __getitem__(self, item: K) -> V: if item in self.dict: return self.dict[item] - else: - self.dict[item] = self.factory_function(item) - return self.dict[item] + self.dict[item] = self.factory_function(item) + return self.dict[item] - def __setitem__(self, key, value) -> None: + def __setitem__(self, key: K, value: V) -> None: self.dict[key] = value - def __delitem__(self, key) -> None: + def __delitem__(self, key: K) -> None: del self.dict[key] @@ -137,7 +137,7 @@ class TwoWayDictionary(tp.MutableMapping[K, V]): :raises ValueError: on being given data from which it is impossible to construct a reverse mapping (ie. same value appears at least twice) """ - __slots__ = ('data', 'reverse_data', '_reverse') + __slots__ = 'data', 'reverse_data', '_reverse' def done(self) -> None: """ @@ -160,7 +160,7 @@ class TwoWayDictionary(tp.MutableMapping[K, V]): self._reverse.reverse_data = self.data self._reverse._reverse = self - def __enter__(self) -> 'TwoWayDictionary': + def __enter__(self) -> TwoWayDictionary: return self def __exit__(self, exc_type, exc_val, exc_tb) -> bool: @@ -179,10 +179,9 @@ class TwoWayDictionary(tp.MutableMapping[K, V]): try: prev_val = self.data[key] + del self.reverse_data[prev_val] except KeyError: pass - else: - del self.reverse_data[prev_val] self.data[key] = value self.reverse_data[value] = key @@ -227,9 +226,9 @@ class DictionaryView(tp.MutableMapping[K, V]): dictionary that contains that key. If not, all updates will be stored in master_dict. If this is True, updates made to keys that are not in this dictionary will go to master_dict. """ - __slots__ = ('assign_to_same_dict', 'master_dict', 'dictionaries', 'propagate_deletes') + __slots__ = 'assign_to_same_dict', 'master_dict', 'dictionaries', 'propagate_deletes' - def __copy__(self) -> 'DictionaryView': + def __copy__(self) -> DictionaryView: return DictionaryView(*copy.copy(self.dictionaries)) def __deepcopy__(self, memo) -> 'DictionaryView': @@ -290,5 +289,4 @@ class DictionaryView(tp.MutableMapping[K, V]): del dictionary[key] return raise KeyError('Key not found') - else: - del self.master_dict[key] + del self.master_dict[key] diff --git a/satella/configuration/sources/derivative.py b/satella/configuration/sources/derivative.py index aa2d9bb88c71c418cff3a9c300e89a854799f8f4..fac0f784df424a383b3393c220556eafa6e23d56 100644 --- a/satella/configuration/sources/derivative.py +++ b/satella/configuration/sources/derivative.py @@ -11,8 +11,10 @@ class AlternativeSource(BaseSource): """ If first source of configuration fails with ConfigurationError, use the next one instead, ad nauseam. + + :ivar: sources (list[BaseSource]) sources to examine left to right """ - __slots__ = ('sources',) + __slots__ = 'sources', def __init__(self, *sources: BaseSource): super().__init__() @@ -69,7 +71,7 @@ class MergingSource(BaseSource): RAISE = 0 # Raise ConfigurationError if one of sources fails SILENT = 1 # Silently continue loading from next files if one fails - __slots__ = ('sources', 'on_fail', 'fail_if_no_sources_are_correct') + __slots__ = 'sources', 'on_fail', 'fail_if_no_sources_are_correct' def __init__(self, *sources: BaseSource, on_fail: int = RAISE, fail_if_no_sources_are_correct: bool = True): @@ -97,7 +99,7 @@ class MergingSource(BaseSource): cfg = merge_dicts(cfg, p) assert isinstance(cfg, dict), 'what merge_dicts returned wasn''t a dict' - if correct_sources == 0 and self.sources and self.fail_if_no_sources_are_correct: + if not correct_sources and self.sources and self.fail_if_no_sources_are_correct: raise ConfigurationError('No source was able to load the configuration') return cfg diff --git a/tests/test_coding/test_structures.py b/tests/test_coding/test_structures.py index d5734587145b1dce9b9f204c2029c744bb212d2d..94c032dc26c9eb044a58cfc9bda6c7186220822c 100644 --- a/tests/test_coding/test_structures.py +++ b/tests/test_coding/test_structures.py @@ -595,7 +595,13 @@ class TestStructures(unittest.TestCase): def test_dirty_dict(self): a = DirtyDict({1: 2, 3: 4}) + self.assertEqual(len(a), 1) + self.assertEqual(set(a.keys()), {1, 3}) self.assertFalse(a.dirty) + self.assertIn(3, a) + b = copy.copy(a) + b[1] = 5 + self.assertEqual(a[1], 2) a[1] = 3 self.assertTrue(a.dirty) a.clear_dirty()