diff --git a/pyguide.md b/pyguide.md
index 4bb0591..1728c0f 100644
--- a/pyguide.md
+++ b/pyguide.md
@@ -31,7 +31,7 @@ See README.md for details.
* [2.17 Function and Method Decorators](#s2.17-function-and-method-decorators)
* [2.18 Threading](#s2.18-threading)
* [2.19 Power Features](#s2.19-power-features)
- * [2.20 Modern Python: Python 3 and from \_\_future\_\_ imports](#s2.20-modern-python)
+ * [2.20 Modern Python: from \_\_future\_\_ imports](#s2.20-modern-python)
* [2.21 Type Annotated Code](#s2.21-type-annotated-code)
- [3 Python Style Rules](#s3-python-style-rules)
* [3.1 Semicolons](#s3.1-semicolons)
@@ -1386,11 +1386,10 @@ to use (for example, `abc.ABCMeta`, `dataclasses`, and `enum`).
-### 2.20 Modern Python: Python 3 and from \_\_future\_\_ imports
+### 2.20 Modern Python: from \_\_future\_\_ imports
-Python 3 is here! While not every project is ready to use it yet,
-all code should be written to be 3 compatible (and tested under 3 when
-possible).
+New language version semantic changes may be gated behind a special future
+import to enable them on a per-file basis within earlier runtimes.
@@ -1398,10 +1397,9 @@ possible).
#### 2.20.1 Definition
-Python 3 is a significant change in the Python language. While existing code is
-often written with 2.7 in mind, there are some simple things to do to make code
-more explicit about its intentions and thus better prepared for use under Python
-3 without modification.
+Being able to turn on some of the more modern features via `from __future__
+import` statements allows early use of features from expected future Python
+versions.
@@ -1409,8 +1407,11 @@ more explicit about its intentions and thus better prepared for use under Python
#### 2.20.2 Pros
-Code written with Python 3 in mind is more explicit and easier to get running
-under Python 3 once all of the dependencies of your project are ready.
+This has proven to make runtime version upgrades smoother as changes can be made
+on a per-file basis while declaring compatibility and preventing regressions
+within those files. Modern code is more maintainable as it is less likely to
+accumulate technical debt that will be problematic during future runtime
+upgrades.
@@ -1418,9 +1419,9 @@ under Python 3 once all of the dependencies of your project are ready.
#### 2.20.3 Cons
-Some people find the additional boilerplate to be ugly. It's unusual to add
-imports to a module that doesn't actually require the features added by the
-import.
+Such code may not work on very old interpreter versions prior to the
+introduction of the needed future statement. The need for this is more common in
+projects supporting an extremely wide variety of environments.
@@ -1430,9 +1431,18 @@ import.
##### from \_\_future\_\_ imports
-Use of `from __future__ import` statements is encouraged. All new code should
-contain the following and existing code should be updated to be compatible when
-possible:
+Use of `from __future__ import` statements is encouraged. It allows a given
+source file to start using more modern Python syntax features today. Once you no
+longer need to run on a version where the features are hidden behind a
+`__future__` import, feel free to remove those lines.
+
+In code that may execute on versions as old as 3.5 rather than >= 3.7, import:
+
+```python
+from __future__ import generator_stop
+```
+
+For legacy code with the burden of continuing to support 2.7, import:
```python
from __future__ import absolute_import
@@ -1440,27 +1450,26 @@ from __future__ import division
from __future__ import print_function
```
-For more information on these imports, see
-[absolute imports](https://www.python.org/dev/peps/pep-0328/),
-[`/` division behavior](https://www.python.org/dev/peps/pep-0238/), and
-[the `print` function](https://www.python.org/dev/peps/pep-3105/).
+For more information read the
+[Python future statement definitions](https://docs.python.org/3/library/__future__.html)
+documentation.
+Please don't remove these imports until you are confident the code is only ever
+used in a sufficiently modern environment. Even if you do not currently use the
+feature a specific future import enables in your code today, keeping it in place
+in the file prevents later modifications of the code from inadvertently
+depending on the older behavior.
-Please don't omit or remove these imports, even if they're not currently used in
-the module, unless the code is Python 3 only. It is better to always have the
-future imports in all files so that they are not forgotten during later edits
-when someone starts using such a feature.
-
-There are other `from __future__` import statements. Use them as you see fit. We
-do not include `unicode_literals` in our recommendations as it is not a clear
-win due to implicit default codec conversion consequences it introduces in many
-places within Python 2.7. Most code is better off with explicit use of `b''` and
-`u''` bytes and unicode string literals as necessary.
+Use other `from __future__` import statements as you see fit. We did not include
+`unicode_literals` in our recommendations for 2.7 as it was not a clear win due
+to implicit default codec conversion consequences it introduced in many places
+within 2.7. Most dual-version 2-and-3 code was better off with explicit use of
+`b''` and `u''` bytes and unicode string literals where necessary.
##### The six, future, and past libraries
-When your project needs to actively support use under both Python 2 and 3, use
-the [six](https://pypi.org/project/six/),
+When your project still needs to support use under both Python 2 and 3, use the
+[six](https://pypi.org/project/six/),
[future](https://pypi.org/project/future/), and
[past](https://pypi.org/project/past/) libraries as you see fit. They exist to
make your code cleaner and life easier.
@@ -3264,40 +3273,30 @@ def check_length(x: AnyStr) -> AnyStr:
The proper type for annotating strings depends on what versions of Python the
code is intended for.
-For Python 3 only code, prefer to use `str`. `Text` is also acceptable. Be
-consistent in using one or the other.
-
-For Python 2 compatible code, use `Text`. In some rare cases, `str` may make
-sense; typically to aid compatibility when the return types aren't the same
-between the two Python versions. Avoid using `unicode`: it doesn't exist in
-Python 3.
-
-The reason this discrepancy exists is because `str` means different things
-depending on the Python version.
+Prefer to use `str`, though `Text` is also acceptable. Be consistent in using
+one or the other. For code that deals with binary data, use `bytes`. For Python
+2 compatible code that processes text data (`str` or `unicode` in Python 2,
+`str` in Python 3), use `Text`.
```python
-No:
-def py2_code(x: str) -> unicode:
+def deals_with_text_data_in_py3(x: str) -> str:
...
-```
-
-For code that deals with binary data, use `bytes`.
-
-```python
def deals_with_binary_data(x: bytes) -> bytes:
...
+def py2_compatible_text_data_processor(x: Text) -> Text:
+ ...
```
-For Python 2 compatible code that processes text data (`str` or `unicode` in
-Python 2, `str` in Python 3), use `Text`. For Python 3 only code that process
-text data, prefer `str`.
+In some uncommon Python 2 compatibility cases, `str` may make sense instead of
+`Text`, typically to aid compatibility when the return types aren't the same
+between Python 2 and Python 3. Never use `unicode` as it doesn't exist in Python
+3. The reason this discrepancy exists is because `str` means something different
+in Python 2 than in Python 3.
+
+No:
```python
-from typing import Text
-...
-def py2_compatible(x: Text) -> Text:
- ...
-def py3_only(x: str) -> str:
+def py2_code(x: str) -> unicode:
...
```
@@ -3307,18 +3306,16 @@ type.
```python
from typing import Text, Union
...
-def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]:
- ...
def py3_only(x: Union[bytes, str]) -> Union[bytes, str]:
...
+def py2_compatible(x: Union[bytes, Text]) -> Union[bytes, Text]:
+ ...
```
If all the string types of a function are always the same, for example if the
return type is the same as the argument type in the code above, use
[AnyStr](#typing-type-var).
-Writing it like this will simplify the process of porting the code to Python 3.
-