From e8df4c68611413e4f469f7a9181015622620ae2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl>
Date: Wed, 9 Jun 2021 18:17:12 +0200
Subject: [PATCH] 2.17.3

---
 CHANGELOG.md                   |  2 ++
 satella/__init__.py            |  2 +-
 satella/coding/misc.py         |  7 ++++---
 tests/test_coding/test_misc.py | 15 +++++++++++++++
 4 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 942fdb5e..07ae3237 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,2 +1,4 @@
 # v2.17.3
 
+* changed the behaviour of `Closeable` to adjust
+  for semi-initialized classes
diff --git a/satella/__init__.py b/satella/__init__.py
index 28fb20fa..0aa561c6 100644
--- a/satella/__init__.py
+++ b/satella/__init__.py
@@ -1 +1 @@
-__version__ = '2.17.3a1'
+__version__ = '2.17.3'
diff --git a/satella/coding/misc.py b/satella/coding/misc.py
index e6277795..ed970434 100644
--- a/satella/coding/misc.py
+++ b/satella/coding/misc.py
@@ -59,9 +59,10 @@ class Closeable:
 
     Can be also used as a context manager, with close() called upon __exit__.
 
-    You should extend both __init__ and close()
+    .. warning:: You should extend both __init__ and close(). Invoke __init__() at the end of
+        your class constructor, this will prevent the destructor from closing on half-initialized classes.
     """
-    __slots__ = ('__finalized',)
+    __slots__ = '__finalized',
 
     def __init__(self):
         self.__finalized = False
@@ -90,7 +91,7 @@ class Closeable:
         try:
             return not self.__finalized
         except AttributeError:
-            raise RuntimeError('__finalized not found, did you forget to call the constructor?')
+            return False        # the device does not need clean up
         finally:
             self.__finalized = True
 
diff --git a/tests/test_coding/test_misc.py b/tests/test_coding/test_misc.py
index 48a71492..5826fbca 100644
--- a/tests/test_coding/test_misc.py
+++ b/tests/test_coding/test_misc.py
@@ -13,6 +13,21 @@ logger = logging.getLogger(__name__)
 
 class TestCase(unittest.TestCase):
 
+    def test_closeable_semi_initialized_classes(self):
+        slf = self
+
+        class Test(Closeable):
+            def __init__(self):
+                raise ValueError()
+                self.a = 5
+                super().__init__()
+
+            def close(self):
+                if super().close():
+                    slf.fail('Tried to close an uninitialized class!')
+
+        self.assertRaises(ValueError, Test)
+
     def test_cant_compare_me(self):
         class Uncomparable:
             def __eq__(self, other):
-- 
GitLab