From 45d8a0da70d6a89fbffe2e6fc39e314d312f34ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl>
Date: Wed, 6 Mar 2024 13:36:46 +0100
Subject: [PATCH] remaining extra fixes

---
 .readthedocs.yaml                             | 10 -------
 LICENSE                                       |  2 +-
 .../coding/structures/dictionaries/objects.py | 26 +++++++++----------
 satella/configuration/sources/derivative.py   |  8 +++---
 tests/test_coding/test_structures.py          |  6 +++++
 5 files changed, 24 insertions(+), 28 deletions(-)

diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 1c60d869..393cba87 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 38e365b6..3c7d6e54 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 b34493a5..cfbe5029 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 aa2d9bb8..fac0f784 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 d5734587..94c032dc 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()
-- 
GitLab