diff --git a/pep_sphinx_extensions/pep_theme/static/style.css b/pep_sphinx_extensions/pep_theme/static/style.css index 9428e8c4239..c60e9e5976a 100644 --- a/pep_sphinx_extensions/pep_theme/static/style.css +++ b/pep_sphinx_extensions/pep_theme/static/style.css @@ -148,6 +148,16 @@ pre { white-space: pre; } +.good pre { + border-left: 3px solid rgba(74, 182, 93, 1); +} +.bad pre { + border-left: 3px solid rgb(244, 76, 78); +} +.maybe pre { + border-left: 3px solid rgb(244, 227, 76); +} + /* Contents rules */ details > summary { cursor: pointer; @@ -434,4 +444,4 @@ dl.footnote > dd { background: transparent; color: inherit; margin-top: 0; -} \ No newline at end of file +} diff --git a/peps/pep-0008.rst b/peps/pep-0008.rst index 05aa89614f9..fa0be88dabc 100644 --- a/peps/pep-0008.rst +++ b/peps/pep-0008.rst @@ -1,13 +1,10 @@ PEP: 8 Title: Style Guide for Python Code -Version: $Revision$ -Last-Modified: $Date$ Author: Guido van Rossum , Barry Warsaw , Alyssa Coghlan Status: Active Type: Process -Content-Type: text/x-rst Created: 05-Jul-2001 Post-History: 05-Jul-2001, 01-Aug-2013 @@ -81,47 +78,54 @@ using Python's implicit line joining inside parentheses, brackets and braces, or using a *hanging indent* [#fn-hi]_. When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to -clearly distinguish itself as a continuation line:: +clearly distinguish itself as a continuation line: - # Correct: +.. code-block:: + :class: good - # Aligned with opening delimiter. - foo = long_function_name(var_one, var_two, - var_three, var_four) + # Correct: - # Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest. - def long_function_name( - var_one, var_two, var_three, - var_four): - print(var_one) + # Aligned with opening delimiter. + foo = long_function_name(var_one, var_two, + var_three, var_four) - # Hanging indents should add a level. - foo = long_function_name( - var_one, var_two, - var_three, var_four) + # Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest. + def long_function_name( + var_one, var_two, var_three, + var_four): + print(var_one) -:: + # Hanging indents should add a level. + foo = long_function_name( + var_one, var_two, + var_three, var_four) - # Wrong: +.. code-block:: + :class: bad - # Arguments on first line forbidden when not using vertical alignment. - foo = long_function_name(var_one, var_two, - var_three, var_four) + # Wrong: - # Further indentation required as indentation is not distinguishable. - def long_function_name( - var_one, var_two, var_three, - var_four): - print(var_one) + # Arguments on first line forbidden when not using vertical alignment. + foo = long_function_name(var_one, var_two, + var_three, var_four) + + # Further indentation required as indentation is not distinguishable. + def long_function_name( + var_one, var_two, var_three, + var_four): + print(var_one) The 4-space rule is optional for continuation lines. -Optional:: +Optional: + +.. code-block:: + :class: good - # Hanging indents *may* be indented to other than 4 spaces. - foo = long_function_name( - var_one, var_two, - var_three, var_four) + # Hanging indents *may* be indented to other than 4 spaces. + foo = long_function_name( + var_one, var_two, + var_three, var_four) .. _`multiline if-statements`: @@ -134,52 +138,61 @@ conflict with the indented suite of code nested inside the ``if``-statement, which would also naturally be indented to 4 spaces. This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside the ``if``-statement. -Acceptable options in this situation include, but are not limited to:: +Acceptable options in this situation include, but are not limited to: + +.. code-block:: + :class: good - # No extra indentation. - if (this_is_one_thing and - that_is_another_thing): - do_something() + # No extra indentation. + if (this_is_one_thing and + that_is_another_thing): + do_something() - # Add a comment, which will provide some distinction in editors - # supporting syntax highlighting. - if (this_is_one_thing and - that_is_another_thing): - # Since both conditions are true, we can frobnicate. - do_something() + # Add a comment, which will provide some distinction in editors + # supporting syntax highlighting. + if (this_is_one_thing and + that_is_another_thing): + # Since both conditions are true, we can frobnicate. + do_something() - # Add some extra indentation on the conditional continuation line. - if (this_is_one_thing - and that_is_another_thing): - do_something() + # Add some extra indentation on the conditional continuation line. + if (this_is_one_thing + and that_is_another_thing): + do_something() (Also see the discussion of whether to break before or after binary operators below.) The closing brace/bracket/parenthesis on multiline constructs may either line up under the first non-whitespace character of the last -line of list, as in:: +line of list, as in: - my_list = [ - 1, 2, 3, - 4, 5, 6, - ] - result = some_function_that_takes_arguments( - 'a', 'b', 'c', - 'd', 'e', 'f', - ) +.. code-block:: + :class: good + + my_list = [ + 1, 2, 3, + 4, 5, 6, + ] + result = some_function_that_takes_arguments( + 'a', 'b', 'c', + 'd', 'e', 'f', + ) or it may be lined up under the first character of the line that -starts the multiline construct, as in:: +starts the multiline construct, as in: + +.. code-block:: + :class: good - my_list = [ - 1, 2, 3, - 4, 5, 6, - ] - result = some_function_that_takes_arguments( - 'a', 'b', 'c', - 'd', 'e', 'f', - ) + my_list = [ + 1, 2, 3, + 4, 5, 6, + ] + result = some_function_that_takes_arguments( + 'a', 'b', 'c', + 'd', 'e', 'f', + ) Tabs or Spaces? --------------- @@ -228,11 +241,14 @@ for line continuation. Backslashes may still be appropriate at times. For example, long, multiple ``with``-statements could not use implicit continuation -before Python 3.10, so backslashes were acceptable for that case:: +before Python 3.10, so backslashes were acceptable for that case: - with open('/path/to/some/file/you/want/to/read') as file_1, \ - open('/path/to/some/file/being/written', 'w') as file_2: - file_2.write(file_1.read()) +.. code-block:: + :class: maybe + + with open('/path/to/some/file/you/want/to/read') as file_1, \ + open('/path/to/some/file/being/written', 'w') as file_2: + file_2.write(file_1.read()) (See the previous discussion on `multiline if-statements`_ for further thoughts on the indentation of such multiline ``with``-statements.) @@ -249,15 +265,18 @@ But this can hurt readability in two ways: the operators tend to get scattered across different columns on the screen, and each operator is moved away from its operand and onto the previous line. Here, the eye has to do extra work to tell which items are added and which are -subtracted:: +subtracted: + +.. code-block:: + :class: bad - # Wrong: - # operators sit far away from their operands - income = (gross_wages + - taxable_interest + - (dividends - qualified_dividends) - - ira_deduction - - student_loan_interest) + # Wrong: + # operators sit far away from their operands + income = (gross_wages + + taxable_interest + + (dividends - qualified_dividends) - + ira_deduction - + student_loan_interest) To solve this readability problem, mathematicians and their publishers follow the opposite convention. Donald Knuth explains the traditional @@ -266,15 +285,18 @@ within a paragraph always break after binary operations and relations, displayed formulas always break before binary operations" [3]_. Following the tradition from mathematics usually results in more -readable code:: +readable code: + +.. code-block:: + :class: good - # Correct: - # easy to match operators with operands - income = (gross_wages - + taxable_interest - + (dividends - qualified_dividends) - - ira_deduction - - student_loan_interest) + # Correct: + # easy to match operators with operands + income = (gross_wages + + taxable_interest + + (dividends - qualified_dividends) + - ira_deduction + - student_loan_interest) In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new @@ -324,22 +346,29 @@ similar policy. Imports ------- -- Imports should usually be on separate lines:: +- Imports should usually be on separate lines: + + .. code-block:: + :class: good + + # Correct: + import os + import sys - # Correct: - import os - import sys + .. code-block:: + :class: bad - :: + # Wrong: + import sys, os - # Wrong: - import sys, os + It's okay to say this though: - It's okay to say this though:: + .. code-block:: + :class: good - # Correct: - from subprocess import Popen, PIPE + # Correct: + from subprocess import Popen, PIPE - Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants. @@ -355,34 +384,46 @@ Imports - Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as - when a directory inside a package ends up on ``sys.path``):: + when a directory inside a package ends up on ``sys.path``): + + .. code-block:: + :class: good - import mypkg.sibling - from mypkg import sibling - from mypkg.sibling import example + import mypkg.sibling + from mypkg import sibling + from mypkg.sibling import example However, explicit relative imports are an acceptable alternative to absolute imports, especially when dealing with complex package layouts - where using absolute imports would be unnecessarily verbose:: + where using absolute imports would be unnecessarily verbose: - from . import sibling - from .sibling import example + .. code-block:: + :class: good + + from . import sibling + from .sibling import example Standard library code should avoid complex package layouts and always use absolute imports. - When importing a class from a class-containing module, it's usually - okay to spell this:: + okay to spell this: + + .. code-block:: + :class: good - from myclass import MyClass - from foo.bar.yourclass import YourClass + from myclass import MyClass + from foo.bar.yourclass import YourClass - If this spelling causes local name clashes, then spell them explicitly:: + If this spelling causes local name clashes, then spell them explicitly: - import myclass - import foo.bar.yourclass + .. code-block:: + :class: good - and use "myclass.MyClass" and "foo.bar.yourclass.YourClass". + import myclass + import foo.bar.yourclass + + and use ``myclass.MyClass`` and ``foo.bar.yourclass.YourClass``. - Wildcard imports (``from import *``) should be avoided, as they make it unclear which names are present in the namespace, @@ -404,21 +445,24 @@ underscores) such as ``__all__``, ``__author__``, ``__version__``, etc. should be placed after the module docstring but before any import statements *except* ``from __future__`` imports. Python mandates that future-imports must appear in the module before any other code except -docstrings:: +docstrings: + +.. code-block:: + :class: good - """This is the example module. + """This is the example module. - This module does stuff. - """ + This module does stuff. + """ - from __future__ import barry_as_FLUFL + from __future__ import barry_as_FLUFL - __all__ = ['a', 'b', 'c'] - __version__ = '0.1' - __author__ = 'Cardinal Biggles' + __all__ = ['a', 'b', 'c'] + __version__ = '0.1' + __author__ = 'Cardinal Biggles' - import os - import sys + import os + import sys String Quotes @@ -442,93 +486,122 @@ Pet Peeves Avoid extraneous whitespace in the following situations: -- Immediately inside parentheses, brackets or braces:: +- Immediately inside parentheses, brackets or braces: + + .. code-block:: + :class: good # Correct: spam(ham[1], {eggs: 2}) - :: + .. code-block:: + :class: bad + + # Wrong: + spam( ham[ 1 ], { eggs: 2 } ) + +- Between a trailing comma and a following close parenthesis: - # Wrong: - spam( ham[ 1 ], { eggs: 2 } ) + .. code-block:: + :class: good -- Between a trailing comma and a following close parenthesis:: + # Correct: + foo = (0,) + + .. code-block:: + :class: bad - # Correct: - foo = (0,) + # Wrong: + bar = (0, ) - :: +- Immediately before a comma, semicolon, or colon: - # Wrong: - bar = (0, ) + .. code-block:: + :class: good -- Immediately before a comma, semicolon, or colon:: + # Correct: + if x == 4: print(x, y); x, y = y, x - # Correct: - if x == 4: print(x, y); x, y = y, x - :: + .. code-block:: + :class: bad - # Wrong: - if x == 4 : print(x , y) ; x , y = y , x + # Wrong: + if x == 4 : print(x , y) ; x , y = y , x - However, in a slice the colon acts like a binary operator, and should have equal amounts on either side (treating it as the operator with the lowest priority). In an extended slice, both colons must have the same amount of spacing applied. Exception: - when a slice parameter is omitted, the space is omitted:: + when a slice parameter is omitted, the space is omitted: - # Correct: - ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] - ham[lower:upper], ham[lower:upper:], ham[lower::step] - ham[lower+offset : upper+offset] - ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)] - ham[lower + offset : upper + offset] + .. code-block:: + :class: good + + # Correct: + ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] + ham[lower:upper], ham[lower:upper:], ham[lower::step] + ham[lower+offset : upper+offset] + ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)] + ham[lower + offset : upper + offset] - :: + .. code-block:: + :class: bad - # Wrong: - ham[lower + offset:upper + offset] - ham[1: 9], ham[1 :9], ham[1:9 :3] - ham[lower : : step] - ham[ : upper] + # Wrong: + ham[lower + offset:upper + offset] + ham[1: 9], ham[1 :9], ham[1:9 :3] + ham[lower : : step] + ham[ : upper] - Immediately before the open parenthesis that starts the argument - list of a function call:: + list of a function call: - # Correct: - spam(1) + .. code-block:: + :class: good - :: + # Correct: + spam(1) + + .. code-block:: + :class: bad - # Wrong: - spam (1) + # Wrong: + spam (1) - Immediately before the open parenthesis that starts an indexing or - slicing:: + slicing: - # Correct: - dct['key'] = lst[index] + .. code-block:: + :class: good - :: + # Correct: + dct['key'] = lst[index] - # Wrong: - dct ['key'] = lst [index] + .. code-block:: + :class: bad + + # Wrong: + dct ['key'] = lst [index] - More than one space around an assignment (or other) operator to - align it with another:: + align it with another: + + .. code-block:: + :class: good - # Correct: - x = 1 - y = 2 - long_variable = 3 + # Correct: + x = 1 + y = 2 + long_variable = 3 - :: + .. code-block:: + :class: bad - # Wrong: - x = 1 - y = 2 - long_variable = 3 + # Wrong: + x = 1 + y = 2 + long_variable = 3 Other Recommendations --------------------- @@ -549,106 +622,134 @@ Other Recommendations whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary - operator:: - - # Correct: - i = i + 1 - submitted += 1 - x = x*2 - 1 - hypot2 = x*x + y*y - c = (a+b) * (a-b) + operator: - :: + .. code-block:: + :class: good - # Wrong: - i=i+1 - submitted +=1 - x = x * 2 - 1 - hypot2 = x * x + y * y - c = (a + b) * (a - b) + # Correct: + i = i + 1 + submitted += 1 + x = x*2 - 1 + hypot2 = x*x + y*y + c = (a+b) * (a-b) + + .. code-block:: + :class: bad + + # Wrong: + i=i+1 + submitted +=1 + x = x * 2 - 1 + hypot2 = x * x + y * y + c = (a + b) * (a - b) - Function annotations should use the normal rules for colons and always have spaces around the ``->`` arrow if present. (See - `Function Annotations`_ below for more about function annotations.):: + `Function Annotations`_ below for more about function annotations.): - # Correct: - def munge(input: AnyStr): ... - def munge() -> PosInt: ... + .. code-block:: + :class: good + + # Correct: + def munge(input: AnyStr): ... + def munge() -> PosInt: ... - :: + .. code-block:: + :class: bad - # Wrong: - def munge(input:AnyStr): ... - def munge()->PosInt: ... + # Wrong: + def munge(input:AnyStr): ... + def munge()->PosInt: ... - Don't use spaces around the ``=`` sign when used to indicate a keyword argument, or when used to indicate a default value for an - *unannotated* function parameter:: + *unannotated* function parameter: - # Correct: - def complex(real, imag=0.0): - return magic(r=real, i=imag) + .. code-block:: + :class: good - :: + # Correct: + def complex(real, imag=0.0): + return magic(r=real, i=imag) + + .. code-block:: + :class: bad - # Wrong: - def complex(real, imag = 0.0): - return magic(r = real, i = imag) + # Wrong: + def complex(real, imag = 0.0): + return magic(r = real, i = imag) When combining an argument annotation with a default value, however, do use - spaces around the ``=`` sign:: + spaces around the ``=`` sign: - # Correct: - def munge(sep: AnyStr = None): ... - def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ... + .. code-block:: + :class: good - :: + # Correct: + def munge(sep: AnyStr = None): ... + def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ... - # Wrong: - def munge(input: AnyStr=None): ... - def munge(input: AnyStr, limit = 1000): ... + .. code-block:: + :class: bad + + # Wrong: + def munge(input: AnyStr=None): ... + def munge(input: AnyStr, limit = 1000): ... - Compound statements (multiple statements on the same line) are - generally discouraged:: + generally discouraged: + + .. code-block:: + :class: good - # Correct: - if foo == 'blah': - do_blah_thing() - do_one() - do_two() - do_three() + # Correct: + if foo == 'blah': + do_blah_thing() + do_one() + do_two() + do_three() + + Rather not: - Rather not:: + .. code-block:: + :class: bad - # Wrong: - if foo == 'blah': do_blah_thing() - do_one(); do_two(); do_three() + # Wrong: + if foo == 'blah': do_blah_thing() + do_one(); do_two(); do_three() - While sometimes it's okay to put an if/for/while with a small body on the same line, never do this for multi-clause statements. Also avoid folding such long lines! - Rather not:: + Rather not: + + .. code-block:: + :class: bad - # Wrong: - if foo == 'blah': do_blah_thing() - for x in lst: total += x - while t < 10: t = delay() + # Wrong: + if foo == 'blah': do_blah_thing() + for x in lst: total += x + while t < 10: t = delay() - Definitely not:: + Definitely not: - # Wrong: - if foo == 'blah': do_blah_thing() - else: do_non_blah_thing() + .. code-block:: + :class: bad - try: something() - finally: cleanup() + # Wrong: + if foo == 'blah': do_blah_thing() + else: do_non_blah_thing() - do_one(); do_two(); do_three(long, argument, - list, like, this) + try: something() + finally: cleanup() - if foo == 'blah': one(); two(); three() + do_one(); do_two(); do_three(long, argument, + list, like, this) + + if foo == 'blah': one(); two(); three() When to Use Trailing Commas @@ -656,15 +757,19 @@ When to Use Trailing Commas Trailing commas are usually optional, except they are mandatory when making a tuple of one element. For clarity, it is recommended to -surround the latter in (technically redundant) parentheses:: +surround the latter in (technically redundant) parentheses: + +.. code-block:: + :class: good - # Correct: - FILES = ('setup.cfg',) + # Correct: + FILES = ('setup.cfg',) -:: +.. code-block:: + :class: bad - # Wrong: - FILES = 'setup.cfg', + # Wrong: + FILES = 'setup.cfg', When trailing commas are redundant, they are often helpful when a version control system is used, when a list of values, arguments or @@ -673,22 +778,26 @@ to put each value (etc.) on a line by itself, always adding a trailing comma, and add the close parenthesis/bracket/brace on the next line. However it does not make sense to have a trailing comma on the same line as the closing delimiter (except in the above case of singleton -tuples):: +tuples): - # Correct: - FILES = [ - 'setup.cfg', - 'tox.ini', - ] - initialize(FILES, - error=True, - ) +.. code-block:: + :class: good -:: + # Correct: + FILES = [ + 'setup.cfg', + 'tox.ini', + ] + initialize(FILES, + error=True, + ) - # Wrong: - FILES = ['setup.cfg', 'tox.ini',] - initialize(FILES, error=True,) +.. code-block:: + :class: bad + + # Wrong: + FILES = ['setup.cfg', 'tox.ini',] + initialize(FILES, error=True,) Comments @@ -736,13 +845,19 @@ Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space. Inline comments are unnecessary and in fact distracting if they state -the obvious. Don't do this:: +the obvious. Don't do this: + +.. code-block:: + :class: bad + + x = x + 1 # Increment x - x = x + 1 # Increment x +But sometimes, this is useful: -But sometimes, this is useful:: +.. code-block:: + :class: good - x = x + 1 # Compensate for border + x = x + 1 # Compensate for border Documentation Strings --------------------- @@ -757,17 +872,24 @@ Conventions for writing good documentation strings - :pep:`257` describes good docstring conventions. Note that most importantly, the ``"""`` that ends a multiline docstring should be - on a line by itself:: + on a line by itself: + + .. code-block:: + :class: good + - """Return a foobang + """Return a foobang - Optional plotz says to frobnicate the bizbaz first. - """ + Optional plotz says to frobnicate the bizbaz first. + """ - For one liner docstrings, please keep the closing ``"""`` on - the same line:: + the same line: - """Return an ex-parrot.""" + .. code-block:: + :class: good + + """Return an ex-parrot.""" Naming Conventions @@ -834,9 +956,12 @@ case convention): with an underscore. - ``single_trailing_underscore_``: used by convention to avoid - conflicts with Python keyword, e.g. :: + conflicts with Python keyword, e.g. : + + .. code-block:: + :class: good - tkinter.Toplevel(master, class_='ClassName') + tkinter.Toplevel(master, class_='ClassName') - ``__double_leading_underscore``: when naming a class attribute, invokes name mangling (inside class FooBar, ``__boo`` becomes @@ -899,12 +1024,15 @@ Type Variable Names Names of type variables introduced in :pep:`484` should normally use CapWords preferring short names: ``T``, ``AnyStr``, ``Num``. It is recommended to add suffixes ``_co`` or ``_contra`` to the variables used to declare covariant -or contravariant behavior correspondingly:: +or contravariant behavior correspondingly: + +.. code-block:: + :class: good - from typing import TypeVar + from typing import TypeVar - VT_co = TypeVar('VT_co', covariant=True) - KT_contra = TypeVar('KT_contra', contravariant=True) + VT_co = TypeVar('VT_co', covariant=True) + KT_contra = TypeVar('KT_contra', contravariant=True) Exception Names ~~~~~~~~~~~~~~~ @@ -1107,15 +1235,19 @@ Programming Recommendations - Use ``is not`` operator rather than ``not ... is``. While both expressions are functionally identical, the former is more readable - and preferred:: + and preferred: - # Correct: - if foo is not None: + .. code-block:: + :class: good + + # Correct: + if foo is not None: - :: + .. code-block:: + :class: bad - # Wrong: - if not foo is None: + # Wrong: + if not foo is None: - When implementing ordering operations with rich comparisons, it is best to implement all six operations (``__eq__``, ``__ne__``, @@ -1134,15 +1266,19 @@ Programming Recommendations that confusion doesn't arise in other contexts. - Always use a def statement instead of an assignment statement that binds - a lambda expression directly to an identifier:: + a lambda expression directly to an identifier: - # Correct: - def f(x): return 2*x + .. code-block:: + :class: good - :: + # Correct: + def f(x): return 2*x + + .. code-block:: + :class: bad - # Wrong: - f = lambda x: 2*x + # Wrong: + f = lambda x: 2*x The first form means that the name of the resulting function object is specifically 'f' instead of the generic ''. This is more @@ -1178,12 +1314,15 @@ Programming Recommendations exception in the new exception message). - When catching exceptions, mention specific exceptions whenever - possible instead of using a bare ``except:`` clause:: + possible instead of using a bare ``except:`` clause: + + .. code-block:: + :class: good - try: - import platform_specific_module - except ImportError: - platform_specific_module = None + try: + import platform_specific_module + except ImportError: + platform_specific_module = None A bare ``except:`` clause will catch SystemExit and KeyboardInterrupt exceptions, making it harder to interrupt a @@ -1209,42 +1348,50 @@ Programming Recommendations - Additionally, for all try/except clauses, limit the ``try`` clause to the absolute minimum amount of code necessary. Again, this - avoids masking bugs:: - - # Correct: - try: - value = collection[key] - except KeyError: - return key_not_found(key) - else: - return handle_value(value) - - :: - - # Wrong: - try: - # Too broad! - return handle_value(collection[key]) - except KeyError: - # Will also catch KeyError raised by handle_value() - return key_not_found(key) + avoids masking bugs: + + .. code-block:: + :class: good + + # Correct: + try: + value = collection[key] + except KeyError: + return key_not_found(key) + else: + return handle_value(value) + + .. code-block:: + :class: bad + + # Wrong: + try: + # Too broad! + return handle_value(collection[key]) + except KeyError: + # Will also catch KeyError raised by handle_value() + return key_not_found(key) - When a resource is local to a particular section of code, use a ``with`` statement to ensure it is cleaned up promptly and reliably after use. A try/finally statement is also acceptable. - Context managers should be invoked through separate functions or methods - whenever they do something other than acquire and release resources:: + whenever they do something other than acquire and release resources: + + .. code-block:: + :class: good - # Correct: - with conn.begin_transaction(): - do_stuff_in_transaction(conn) + # Correct: + with conn.begin_transaction(): + do_stuff_in_transaction(conn) - :: + .. code-block:: + :class: bad - # Wrong: - with conn: - do_stuff_in_transaction(conn) + # Wrong: + with conn: + do_stuff_in_transaction(conn) The latter example doesn't provide any information to indicate that the ``__enter__`` and ``__exit__`` methods are doing something other @@ -1256,102 +1403,128 @@ Programming Recommendations any return statement returns an expression, any return statements where no value is returned should explicitly state this as ``return None``, and an explicit return statement should be present at the - end of the function (if reachable):: + end of the function (if reachable): - # Correct: + .. code-block:: + :class: good + + # Correct: - def foo(x): - if x >= 0: - return math.sqrt(x) - else: - return None + def foo(x): + if x >= 0: + return math.sqrt(x) + else: + return None - def bar(x): - if x < 0: - return None - return math.sqrt(x) + def bar(x): + if x < 0: + return None + return math.sqrt(x) - :: + .. code-block:: + :class: bad - # Wrong: + # Wrong: - def foo(x): - if x >= 0: - return math.sqrt(x) + def foo(x): + if x >= 0: + return math.sqrt(x) - def bar(x): - if x < 0: - return - return math.sqrt(x) + def bar(x): + if x < 0: + return + return math.sqrt(x) - Use ``''.startswith()`` and ``''.endswith()`` instead of string slicing to check for prefixes or suffixes. - startswith() and endswith() are cleaner and less error prone:: + startswith() and endswith() are cleaner and less error prone: - # Correct: - if foo.startswith('bar'): + .. code-block:: + :class: good - :: + # Correct: + if foo.startswith('bar'): + + .. code-block:: + :class: bad - # Wrong: - if foo[:3] == 'bar': + # Wrong: + if foo[:3] == 'bar': - Object type comparisons should always use isinstance() instead of - comparing types directly:: + comparing types directly: - # Correct: - if isinstance(obj, int): + .. code-block:: + :class: good - :: + # Correct: + if isinstance(obj, int): - # Wrong: - if type(obj) is type(1): + .. code-block:: + :class: bad + + # Wrong: + if type(obj) is type(1): - For sequences, (strings, lists, tuples), use the fact that empty - sequences are false:: + sequences are false: + + .. code-block:: + :class: good - # Correct: - if not seq: - if seq: + # Correct: + if not seq: + if seq: - :: + .. code-block:: + :class: bad - # Wrong: - if len(seq): - if not len(seq): + # Wrong: + if len(seq): + if not len(seq): - Don't write string literals that rely on significant trailing whitespace. Such trailing whitespace is visually indistinguishable and some editors (or more recently, reindent.py) will trim them. -- Don't compare boolean values to True or False using ``==``:: +- Don't compare boolean values to True or False using ``==``: + + .. code-block:: + :class: good - # Correct: - if greeting: + # Correct: + if greeting: - :: + .. code-block:: + :class: bad - # Wrong: - if greeting == True: + # Wrong: + if greeting == True: - Worse:: + Worse: - # Wrong: - if greeting is True: + .. code-block:: + :class: bad + + # Wrong: + if greeting is True: - Use of the flow control statements ``return``/``break``/``continue`` within the finally suite of a ``try...finally``, where the flow control statement would jump outside the finally suite, is discouraged. This is because such statements will implicitly cancel any active exception - that is propagating through the finally suite:: + that is propagating through the finally suite: + + .. code-block:: + :class: bad - # Wrong: - def foo(): - try: - 1 / 0 - finally: - return 42 + # Wrong: + def foo(): + try: + 1 / 0 + finally: + return 42 Function Annotations -------------------- @@ -1376,9 +1549,12 @@ annotations have changed. refactorings. - For code that wants to make a different use of function annotations - it is recommended to put a comment of the form:: + it is recommended to put a comment of the form: - # type: ignore + .. code-block:: + :class: good + + # type: ignore near the top of the file; this tells type checkers to ignore all annotations. (More fine-grained ways of disabling complaints from @@ -1409,25 +1585,29 @@ similar to those on function annotations described above: - There should be no space before the colon. - If an assignment has a right hand side, then the equality sign should have - exactly one space on both sides:: + exactly one space on both sides: + + .. code-block:: + :class: good - # Correct: + # Correct: - code: int + code: int - class Point: - coords: Tuple[int, int] - label: str = '' + class Point: + coords: Tuple[int, int] + label: str = '' - :: + .. code-block:: + :class: bad - # Wrong: + # Wrong: - code:int # No space after colon - code : int # Space before colon + code:int # No space after colon + code : int # Space before colon - class Test: - result: int=0 # No spaces around equality sign + class Test: + result: int=0 # No spaces around equality sign - Although the :pep:`526` is accepted for Python 3.6, the variable annotation syntax is the preferred syntax for stub files on all versions of Python @@ -1462,14 +1642,3 @@ Copyright ========= This document has been placed in the public domain. - - - -.. - Local Variables: - mode: indented-text - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 70 - coding: utf-8 - End: