publish all pending posts

    

index 0118d67..6148afa 100644
@@ -12,16 +12,6 @@ Reasons to read posts from the cannel rather than here:

You don't need telegram to read the channel using the link above. If neither of it stops you, sure, go ahead, read it here.

-## To publish
-
-+ union
-+ lookup-error
-+ is
-+ del
-+ del2
-+ gc_is_finalized
-+ warnings
-
## To write

These are ideas for future posts. Let me know if you want to write a guest post on any of these topics.
diff --git a/pythonetc/del.md b/pythonetc/del.md
index 908180f..9286063 100644
--- a/pythonetc/del.md
+++ b/pythonetc/del.md
@@ -1,5 +1,7 @@
# del

+Published: 2022-08-23.
+
The del statement is used to delete things. It has a few distinct behaviors, depending on what is the specified target.

If a variable specified, it will be removed from the scope in which it is defined:
diff --git a/pythonetc/del2.md b/pythonetc/del2.md
index 8207560..6fb06d2 100644
--- a/pythonetc/del2.md
+++ b/pythonetc/del2.md
@@ -1,6 +1,8 @@
# __del__

-The method __del__ is called on the object by the grabage collector when the last reference to the object is removed:
+Published: 2022-08-30.
+
+The method __del__ is called on the object by the garbage collector when the last reference to the object is removed:

python
class A:
@@ -19,7 +21,7 @@ f()
# destroying


-The method is used by python file object to close the descriptor when you don't need it anymore:
+The method is used by Python's file object to close the descriptor when you don't need it anymore:

python
def f():
@@ -27,9 +29,9 @@ def f():
...


-However, you cannot safely rely on that the destructor (this is how it's called in other languages, like C) will be ever called. For instance, it can be not true in PyPy, MicroPython, or just if tthe garbage collector is disabled using gc.disable().
+However, you cannot safely rely on that the destructor (this is how it's called in other languages, like C) will be ever called. For instance, it can be not true in PyPy, MicroPython, or just if the garbage collector is disabled using gc.disable().

-The thumb up rule is to use the destructor for unimportant things. For example, aiohttp.ClientSession uses __del__ to warn about an unclosed session:
+The thumb-up rule is to use the destructor only for unimportant things. For example, aiohttp.ClientSession uses __del__ to warn about an unclosed session:

python
def __del__(self) -> None:
diff --git a/pythonetc/gc-is-finalized.md b/pythonetc/gc-is-finalized.md
index 2e18ee5..ef27a5d 100644
--- a/pythonetc/gc-is-finalized.md
+++ b/pythonetc/gc-is-finalized.md
@@ -1,6 +1,8 @@
# gc.is_finalized

-By using __del__ and global variables it is possible to leave a reference to the object after it was "destroyed":
+Published: 2022-09-06.
+
+By using __del__ and global variables, it is possible to leave a reference to the object after it was "destroyed":

python
runner = None
@@ -19,7 +21,7 @@ print(runner)
# <__main__.Lazarus object at 0x7f853df0a790>


-In the example above, runner points to exactly the same object as lazarus did and it's not destroyed. If you remove this reference, the object will stay in the memory forever because it's not tracked by the garbage collector anymore:
+In the example above, runner points to the same object as lazarus did and it's not destroyed. If you remove this reference, the object will stay in the memory forever because it's not tracked by the garbage collector anymore:

python
del runner  # it will NOT produce "destroying" message
@@ -27,7 +29,7 @@ del runner  # it will NOT produce "destroying" message

This can lead to a strange situation when you have an object that escapes the tracking and will be never collected.

-In python 3.9, the function gc.is_finalized was introduced that tells you if the given object is a such runner:
+In Python 3.9, the function [gc.is_finalized](https://docs.python.org/3/library/gc.html#gc.is_finalized) was introduced that tells you if the given object is a such runner:

python
import gc
@@ -37,4 +39,4 @@ del lazarus
gc.is_finalized(runner)  # True


-It's hard to imagine situation when you'll actually need it, though. The main conclusion you can make out of it is that you can break things with a destructor, so don't overuse it.
+It's hard to imagine a situation when you'll need it, though. The main conclusion you can make out of it is that you can break things with a destructor, so don't overuse it.
diff --git a/pythonetc/is.md b/pythonetc/is.md
index 558309a..8c8bd9a 100644
--- a/pythonetc/is.md
+++ b/pythonetc/is.md
@@ -1,5 +1,7 @@
# is

+Published: 2022-08-16.
+
The operator is checks if the two given objects are the same object in the memory:

python
@@ -25,15 +27,9 @@ type(1) == int  # True
So, when to use is and when to use ==? There are some best practices:

+ Use is to compare with None: var is None.
-
-+ Use is to compare with True and False. However, don't explicitly check for True and False in conditions, prefer just if user.admin instead of if user.admin is True. However, the latter can be useful in tests: assert actual is True.
-
-+ Use isinstance to compare types: if isinstance(user, LoggedInUser). The big difference is that it allows subclasses. So if you have a class Admin which is subclass of LoggedInUser, it will pass this check.
-
++ Use is to compare with True and False. However, don't explicitly check for True and False in conditions, prefer just if user.admin instead of if user.admin is True. Still, the latter can be useful in tests: assert actual is True.
++ Use isinstance to compare types: if isinstance(user, LoggedInUser). The big difference is that it allows subclasses. So if you have a class Admin which is subclass of LoggedInUser, it will pass isinstance check.
+ Use is in some rare cases when you explicitly want to allow only the given type without subclasses: type(user) is Admin. Keep in mind, that mypy will refine the type only for isinstance but not for type is.
-
+ Use is to compare [enum](https://docs.python.org/3/library/enum.html) members: color is Color.RED.
-
+ Use == in ORMs and query builders like [sqlalchemy](https://www.sqlalchemy.org/): session.query(User).filter(User.admin == True). The reason is that is behavior cannot be redefined using magic methods but == can (using __eq__).
-
+ Use == in all other cases. In particular, always use == to compare values: answer == 42.
diff --git a/pythonetc/lookup-error.md b/pythonetc/lookup-error.md
index bb61838..08d9745 100644
--- a/pythonetc/lookup-error.md
+++ b/pythonetc/lookup-error.md
@@ -1,10 +1,16 @@
# LookupError

+Published: 2022-08-09
+
LookupError is a base class for IndexError and KeyError:

python
+LookupError.__subclasses__()
+# [IndexError, KeyError, encodings.CodecRegistryError]
+
KeyError.mro()
# [KeyError, LookupError, Exception, BaseException, object]
+
IndexError.mro()
# [IndexError, LookupError, Exception, BaseException, object]

diff --git a/pythonetc/union.md b/pythonetc/union.md
index 56688e0..40cd4d7 100644
--- a/pythonetc/union.md
+++ b/pythonetc/union.md
@@ -1,8 +1,8 @@
# Union alias (PEP-604)

-Published: 28 December 2021, 18:00.
+Published: 2022-08-02.

-[PEP-604](https://www.python.org/dev/peps/pep-0604/) (landed in Python 3.10) introduced a new short syntax for typing.Union ([as we predicted](https://t.me/pythonetc/569)):
+[PEP-604](https://www.python.org/dev/peps/pep-0604/) (landed in Python 3.10) introduced a new short syntax for typing.Union ([as I predicted](https://t.me/pythonetc/569), but I messed up union with intersection, shame on me):

python
def greet(name: str) -> str | None:
@@ -11,4 +11,4 @@ def greet(name: str) -> str | None:
return f"Hello, {name}"


-You already can use it in older Python versions by adding described in the previous post from __future__ import annotations, [mypy](http://mypy-lang.org/) will understand you.
+You already can use it in older Python versions by adding from __future__ import annotations, type checkers will understand you.
diff --git a/pythonetc/warnings.md b/pythonetc/warnings.md
index 79a78a3..ae0e6bb 100644
--- a/pythonetc/warnings.md
+++ b/pythonetc/warnings.md
@@ -1,6 +1,6 @@
# warnings

-The module [warnings](https://docs.python.org/3/library/warnings.html) allows to print, well, warnings. Most often, it is used to warn users of a library that the module, function, or argument they use is deprecated.
+The module [warnings](https://docs.python.org/3/library/warnings.html) allows to print, you've guessed it, warnings. Most often, it is used to warn users of a library that the module, function, or argument they use is deprecated.

python
import warnings
@@ -21,11 +21,12 @@ f()
The output:

python
-example.py:7: DeprecationWarning: function f is deprecated, use g instead
+example.py:7: DeprecationWarning:
+function f is deprecated, use g instead
warnings.warn(


-Note that DeprecationWarning, as well as [other warning categories](https://docs.python.org/3/library/warnings.html#warning-categories), is a built-in and doesn't need to be imported from anywhere.
+Note that DeprecationWarning, as well as [other warning categories](https://docs.python.org/3/library/warnings.html#warning-categories), is built-in and doesn't need to be imported from anywhere.

When running tests, pytest will collect all warnings and report them at the end. If you want to get the full traceback to the warning or enter there with a debugger, the easiest way to do so is to turn all warnings into exceptions:

@@ -33,7 +34,7 @@ When running tests, pytest will collect all warnings and report them at the end.
warnings.filterwarnings("error")


-On the production, you can suppress warnings. Or, better, turn them into proper log records, so it will collected wherever you collect logs:
+On the production, you can suppress warnings. Or, better, turn them into proper log records, so they will be collected wherever you collect logs:

python
import logging