Project import generated by Copybara.

PiperOrigin-RevId: 440926376
This commit is contained in:
Google Python team 2022-04-11 17:17:08 +00:00 committed by Gregory P. Smith [Google LLC]
parent af78b49ac4
commit d2ca0a820a

View File

@ -213,8 +213,8 @@ that the arguments are actually unused.
Use `import` statements for packages and modules only, not for individual
classes or functions. Classes imported from the
[typing module](#typing-imports),
[typing_extensions module](https://github.com/python/typing/tree/master/typing_extensions),
[`typing` module](#typing-imports), [`collections.abc` module](#typing-imports),
[`typing_extensions` module](https://github.com/python/typing/tree/master/typing_extensions),
and redirects from the
[six.moves module](https://six.readthedocs.io/#module-six.moves)
are exempt from this rule.
@ -254,8 +254,9 @@ Module names can still collide. Some module names are inconveniently long.
* Use `import x` for importing packages and modules.
* Use `from x import y` where `x` is the package prefix and `y` is the module
name with no prefix.
* Use `from x import y as z` if two modules named `y` are to be imported or if
`y` is an inconveniently long name.
* Use `from x import y as z` if two modules named `y` are to be imported, if
`y` conflicts with a top-level name defined in the current module, or if `y`
is an inconveniently long name.
* Use `import y as z` only when `z` is a standard abbreviation (e.g., `np` for
`numpy`).
@ -313,7 +314,7 @@ Yes:
import absl.flags
from doctor.who import jodie
FLAGS = absl.flags.FLAGS
_FOO = absl.flags.DEFINE_string(...)
```
```python
@ -322,7 +323,7 @@ Yes:
from absl import flags
from doctor.who import jodie
FLAGS = flags.FLAGS
_FOO = flags.DEFINE_string(...)
```
*(assume this file lives in `doctor/who/` where `jodie.py` also exists)*
@ -416,7 +417,7 @@ Exceptions must follow certain conditions:
# guarantee this specific behavioral reaction to API misuse.
raise ValueError(f'Min. port must be at least 1024, not {minimum}.')
port = self._find_next_open_port(minimum)
if not port:
if port is None:
raise ConnectionError(
f'Could not connect to service on port {minimum} or higher.')
assert port >= minimum, (
@ -509,13 +510,14 @@ assignments to global variables are done when the module is first imported.
Avoid global variables.
While they are technically variables, module-level constants are permitted and
encouraged. For example: `_MAX_HOLY_HANDGRENADE_COUNT = 3`. Constants must be
named using all caps with underscores. See [Naming](#s3.16-naming) below.
If needed, global variables should be declared at the module level and made
internal to the module by prepending an `_` to the name. External access to
global variables must be done through public module-level functions. See
[Naming](#s3.16-naming) below.
If needed, globals should be declared at the module level and made internal to
the module by prepending an `_` to the name. External access must be done
through public module-level functions. See [Naming](#s3.16-naming) below.
While module-level constants are technically variables, they are permitted and
encouraged. For example: `MAX_HOLY_HANDGRENADE_COUNT = 3`. Constants must be
named using all caps with underscores. See [Naming](#s3.16-naming) below.
<a id="s2.6-nested"></a>
<a id="26-nested"></a>
@ -955,11 +957,14 @@ Yes: def foo(a, b: Sequence = ()): # Empty tuple OK since tuples are immutable
```
```python
from absl import flags
_FOO = flags.DEFINE_string(...)
No: def foo(a, b=[]):
...
No: def foo(a, b=time.time()): # The time the module was loaded???
...
No: def foo(a, b=FLAGS.my_thing): # sys.argv has not yet been parsed...
No: def foo(a, b=_FOO.value): # sys.argv has not yet been parsed...
...
No: def foo(a, b: Mapping = {}): # Could still get passed to unchecked code
...
@ -1471,7 +1476,7 @@ Type annotations (or "type hints") are for function or method arguments and
return values:
```python
def func(a: int) -> List[int]:
def func(a: int) -> list[int]:
```
You can also declare the type of a variable using similar
@ -2026,7 +2031,7 @@ aptly described using a one-line docstring.
([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html)),
which frequently documents a tuple return value as if it were multiple
return values with individual names (never mentioning the tuple). Instead,
describe such a return value as: "Returns a tuple (mat_a, mat_b), where
describe such a return value as: "Returns: A tuple (mat_a, mat_b), where
mat_a is ..., and ...". The auxiliary names in the docstring need not
necessarily correspond to any internal names used in the function body (as
those are not part of the API).
@ -2044,7 +2049,7 @@ aptly described using a one-line docstring.
def fetch_smalltable_rows(table_handle: smalltable.Table,
keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False,
) -> Mapping[bytes, Tuple[str, ...]]:
) -> Mapping[bytes, tuple[str, ...]]:
"""Fetches rows from a Smalltable.
Retrieves rows pertaining to the given keys from the Table instance
@ -2081,7 +2086,7 @@ Similarly, this variation on `Args:` with a line break is also allowed:
def fetch_smalltable_rows(table_handle: smalltable.Table,
keys: Sequence[Union[bytes, str]],
require_all_keys: bool = False,
) -> Mapping[bytes, Tuple[str, ...]]:
) -> Mapping[bytes, tuple[str, ...]]:
"""Fetches rows from a Smalltable.
Retrieves rows pertaining to the given keys from the Table instance
@ -2215,23 +2220,20 @@ punctuation, spelling, and grammar help with that goal.
Use an
[f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings),
the `%` operator, or the `format` method for formatting strings, even when the
parameters are all strings. Use your best judgment to decide between `+` and `%`
(or `format`) though. Do not use `%` or the `format` method for pure
concatenation.
parameters are all strings. Use your best judgment to decide between `+` and
string formatting.
```python
Yes: x = a + b
Yes: x = f'name: {name}; score: {n}'
x = '%s, %s!' % (imperative, expletive)
x = '{}, {}'.format(first, second)
x = 'name: %s; score: %d' % (name, n)
x = 'name: {}; score: {}'.format(name, n)
x = f'name: {name}; score: {n}'
x = a + b
```
```python
No: x = '%s%s' % (a, b) # use + in this case
x = '{}{}'.format(a, b) # use + in this case
x = first + ', ' + second
No: x = first + ', ' + second
x = 'name: ' + name + '; score: ' + str(n)
```
@ -2524,7 +2526,7 @@ event ("Remove this code when all clients can handle XML responses.").
### 3.13 Imports formatting
Imports should be on separate lines; there are
[exceptions for `typing` imports](#typing-imports).
[exceptions for `typing` and `collections.abc` imports](#typing-imports).
E.g.:
@ -2692,7 +2694,8 @@ change in complexity.
`module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`,
`function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`,
`function_parameter_name`, `local_var_name`.
`function_parameter_name`, `local_var_name`, `query_proper_noun_for_thing`,
`send_acronym_via_https`.
Function names, variable names, and filenames should be descriptive; eschew
@ -2713,6 +2716,8 @@ Always use a `.py` filename extension. Never use dashes.
- counters or iterators (e.g. `i`, `j`, `k`, `v`, et al.)
- `e` as an exception identifier in `try/except` statements.
- `f` as a file handle in `with` statements
- private [`TypeVar`s](#typing-type-var) with no constraints (e.g. `_T`,
`_U`, `_V`)
Please be mindful not to abuse single-character naming. Generally speaking,
descriptiveness should be proportional to the name's scope of visibility.
@ -2949,6 +2954,8 @@ the function into smaller and more manageable pieces.
* In methods, only annotate `self`, or `cls` if it is necessary for proper
type information. e.g., `@classmethod def create(cls: Type[T]) -> T: return
cls()`
* Similarly, don't feel compelled to annotate the return value of `__init__`
(where `None` is the only valid option).
* If any other variable or a returned type should not be expressed, use `Any`.
* You are not required to annotate all the functions in a module.
- At least annotate your public APIs.
@ -2993,7 +3000,7 @@ is too long, indent by 4 in a new line.
```python
def my_method(
self, first_var: int) -> Tuple[MyLongType1, MyLongType1]:
self, first_var: int) -> tuple[MyLongType1, MyLongType1]:
...
```
@ -3005,7 +3012,7 @@ closing parenthesis with the `def`.
Yes:
def my_method(
self, other_arg: Optional[MyLongType]
) -> Dict[OtherLongType, MyLongType]:
) -> dict[OtherLongType, MyLongType]:
...
```
@ -3017,7 +3024,7 @@ opening one, but this is less readable.
No:
def my_method(self,
other_arg: Optional[MyLongType]
) -> Dict[OtherLongType, MyLongType]:
) -> dict[OtherLongType, MyLongType]:
...
```
@ -3027,9 +3034,9 @@ too long to be on a single line (try to keep sub-types unbroken).
```python
def my_method(
self,
first_var: Tuple[List[MyLongType1],
List[MyLongType2]],
second_var: List[Dict[
first_var: tuple[list[MyLongType1],
list[MyLongType2]],
second_var: list[dict[
MyLongType3, MyLongType4]]) -> None:
...
```
@ -3146,7 +3153,7 @@ long:
```python
_ShortName = module_with_long_name.TypeWithLongName
ComplexMap = Mapping[str, List[Tuple[int, int]]]
ComplexMap = Mapping[str, list[tuple[int, int]]]
```
Other examples are complex nested types and multiple return variables from a
@ -3207,9 +3214,9 @@ have a single repeated type or a set number of elements with different types.
The latter is commonly used as the return type from a function.
```python
a = [1, 2, 3] # type: List[int]
b = (1, 2, 3) # type: Tuple[int, ...]
c = (1, "2", 3.5) # type: Tuple[int, str, float]
a = [1, 2, 3] # type: list[int]
b = (1, 2, 3) # type: tuple[int, ...]
c = (1, "2", 3.5) # type: tuple[int, str, float]
```
<a id="s3.19.10-typevars"></a>
@ -3227,10 +3234,10 @@ function `TypeVar` is a common way to use them.
Example:
```python
from typing import List, TypeVar
T = TypeVar("T")
from typing import TypeVar
_T = TypeVar("_T")
...
def next(l: List[T]) -> T:
def next(l: list[_T]) -> _T:
return l.pop()
```
@ -3254,6 +3261,26 @@ def check_length(x: AnyStr) -> AnyStr:
raise ValueError()
```
A TypeVar must have a descriptive name, unless it meets all of the following
criteria:
* not externally visible
* not constrained
```python
Yes:
_T = TypeVar("_T")
AddableType = TypeVar("AddableType", int, float, str)
AnyFunction = TypeVar("AnyFunction", bound=Callable)
```
```python
No:
T = TypeVar("T")
_T = TypeVar("_T", int, float, str)
_F = TypeVar("_F", bound=Callable)
```
<a id="s3.19.11-string-types"></a>
<a id="s3.19.11-strings"></a>
<a id="31911-string-types"></a>
@ -3314,19 +3341,21 @@ return type is the same as the argument type in the code above, use
<a id="typing-imports"></a>
#### 3.19.12 Imports For Typing
For classes from the `typing` module, always import the class itself. You are
explicitly allowed to import multiple specific classes on one line from the
`typing` module. Ex:
For classes from the `typing` and `collections.abc` modules for use in
annotations, always import the class itself. This keeps common annotations more
concise and matches typing practices used around the world. You are explicitly
allowed to import multiple specific classes on one line from the `typing` and
`collections.abc` modules. Ex:
```python
from typing import Any, Dict, Optional
from collections.abc import Mapping, Sequence
from typing import Any, Union
```
Given that this way of importing from `typing` adds items to the local
namespace, any names in `typing` should be treated similarly to keywords, and
not be defined in your Python code, typed or not. If there is a collision
between a type and an existing name in a module, import it using `import x as
y`.
Given that this way of importing adds items to the local namespace, names in
`typing` or `collections.abc` should be treated similarly to keywords, and not
be defined in your Python code, typed or not. If there is a collision between a
type and an existing name in a module, import it using `import x as y`.
```python
from typing import Any as AnyType
@ -3400,12 +3429,12 @@ When annotating, prefer to specify type parameters for generic types; otherwise,
[the generics' parameters will be assumed to be `Any`](https://www.python.org/dev/peps/pep-0484/#the-any-type).
```python
def get_names(employee_ids: List[int]) -> Dict[int, Any]:
def get_names(employee_ids: list[int]) -> dict[int, Any]:
...
```
```python
# These are both interpreted as get_names(employee_ids: List[Any]) -> Dict[Any, Any]
# These are both interpreted as get_names(employee_ids: list[Any]) -> dict[Any, Any]
def get_names(employee_ids: list) -> Dict:
...
@ -3418,13 +3447,13 @@ remember that in many cases [`TypeVar`](#typing-type-var) might be more
appropriate:
```python
def get_names(employee_ids: List[Any]) -> Dict[Any, str]:
def get_names(employee_ids: list[Any]) -> dict[Any, str]:
"""Returns a mapping from employee ID to employee name for given IDs."""
```
```python
T = TypeVar('T')
def get_names(employee_ids: List[T]) -> Dict[T, str]:
_T = TypeVar('_T')
def get_names(employee_ids: list[_T]) -> dict[_T, str]:
"""Returns a mapping from employee ID to employee name for given IDs."""
```