From 20f74c20f7efe80f0b0199153934dddd80e21d8e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Langa?=
Date: Wed, 26 Aug 2020 18:18:14 +0200
Subject: [PATCH 0001/1034] Stop running Primer on macOS as it's flaky on
GitHub Actions
---
.github/workflows/primer.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/primer.yml b/.github/workflows/primer.yml
index b5dea5e7139..9b10db0d285 100644
--- a/.github/workflows/primer.yml
+++ b/.github/workflows/primer.yml
@@ -9,7 +9,7 @@ jobs:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8]
- os: [ubuntu-latest, macOS-latest, windows-latest]
+ os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v2
From 1ebe9b70c5624da964364841e30a2e3ffe109c4e Mon Sep 17 00:00:00 2001
From: Yurii Karabas <1998uriyyo@gmail.com>
Date: Wed, 24 Jun 2020 00:33:05 +0300
Subject: [PATCH 0002/1034] Simplify black code by using generator expressions
---
src/black/__init__.py | 44 +++++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 200e31fd458..954b93c77d7 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -641,10 +641,9 @@ def path_empty(
"""
Exit if there is no `src` provided for formatting
"""
- if len(src) == 0:
- if verbose or not quiet:
- out(msg)
- ctx.exit(0)
+ if not src and (verbose or not quiet):
+ out(msg)
+ ctx.exit(0)
def reformat_one(
@@ -928,7 +927,7 @@ def format_file_contents(src_contents: str, *, fast: bool, mode: Mode) -> FileCo
valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
`mode` is passed to :func:`format_str`.
"""
- if src_contents.strip() == "":
+ if not src_contents.strip():
raise NothingChanged
dst_contents = format_str(src_contents, mode=mode)
@@ -1062,7 +1061,7 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -> Node:
"""Given a string with source, return the lib2to3 Node."""
- if src_txt[-1:] != "\n":
+ if not src_txt.endswith("\n"):
src_txt += "\n"
for grammar in get_grammars(set(target_versions)):
@@ -1547,11 +1546,10 @@ def is_triple_quoted_string(self) -> bool:
def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
"""If so, needs to be split before emitting."""
- for leaf in self.leaves:
- if leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit:
- return True
-
- return False
+ return any(
+ leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit
+ for leaf in self.leaves
+ )
def contains_uncollapsable_type_comments(self) -> bool:
ignored_ids = set()
@@ -3992,12 +3990,13 @@ class StringParenWrapper(CustomSplitMapMixin, BaseStringSplitter):
def do_splitter_match(self, line: Line) -> TMatchResult:
LL = line.leaves
- string_idx = None
- string_idx = string_idx or self._return_match(LL)
- string_idx = string_idx or self._else_match(LL)
- string_idx = string_idx or self._assert_match(LL)
- string_idx = string_idx or self._assign_match(LL)
- string_idx = string_idx or self._dict_match(LL)
+ string_idx = (
+ self._return_match(LL)
+ or self._else_match(LL)
+ or self._assert_match(LL)
+ or self._assign_match(LL)
+ or self._dict_match(LL)
+ )
if string_idx is not None:
string_value = line.leaves[string_idx].value
@@ -4196,7 +4195,7 @@ def do_transform(self, line: Line, string_idx: int) -> Iterator[TResult[Line]]:
is_valid_index = is_valid_index_factory(LL)
insert_str_child = insert_str_child_factory(LL[string_idx])
- comma_idx = len(LL) - 1
+ comma_idx = -1
ends_with_comma = False
if LL[comma_idx].type == token.COMMA:
ends_with_comma = True
@@ -4444,11 +4443,10 @@ def contains_pragma_comment(comment_list: List[Leaf]) -> bool:
of the more common static analysis tools for python (e.g. mypy, flake8,
pylint).
"""
- for comment in comment_list:
- if comment.value.startswith(("# type:", "# noqa", "# pylint:")):
- return True
-
- return False
+ return any(
+ comment.value.startswith(("# type:", "# noqa", "# pylint:"))
+ for comment in comment_list
+ )
def insert_str_child_factory(string_leaf: Leaf) -> Callable[[LN], None]:
From 4ca92ac91c944b252caf8c2265e5854f839a66f4 Mon Sep 17 00:00:00 2001
From: Yurii Karabas <1998uriyyo@gmail.com>
Date: Wed, 26 Aug 2020 09:35:21 +0300
Subject: [PATCH 0003/1034] Revert contains_standalone_comments function
changes
---
src/black/__init__.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 954b93c77d7..96dd0e46e7b 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -1546,10 +1546,11 @@ def is_triple_quoted_string(self) -> bool:
def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
"""If so, needs to be split before emitting."""
- return any(
- leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit
- for leaf in self.leaves
- )
+ for leaf in self.leaves:
+ if leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit:
+ return True
+
+ return False
def contains_uncollapsable_type_comments(self) -> bool:
ignored_ids = set()
From e268cbaf668cc86b1e6aa52e52483cf4592e176c Mon Sep 17 00:00:00 2001
From: Yurii Karabas <1998uriyyo@gmail.com>
Date: Wed, 26 Aug 2020 13:43:00 +0300
Subject: [PATCH 0004/1034] Revert contains_pragma_comment function changes
---
src/black/__init__.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 96dd0e46e7b..f51a50d3612 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -4444,10 +4444,11 @@ def contains_pragma_comment(comment_list: List[Leaf]) -> bool:
of the more common static analysis tools for python (e.g. mypy, flake8,
pylint).
"""
- return any(
- comment.value.startswith(("# type:", "# noqa", "# pylint:"))
- for comment in comment_list
- )
+ for comment in comment_list:
+ if comment.value.startswith(("# type:", "# noqa", "# pylint:")):
+ return True
+
+ return False
def insert_str_child_factory(string_leaf: Leaf) -> Callable[[LN], None]:
From 5f78401b2863c4c2e8417905fa8b8bf4d648510d Mon Sep 17 00:00:00 2001
From: Rowan Rodrik van der Molen
Date: Sat, 11 Jul 2020 21:20:31 +0200
Subject: [PATCH 0005/1034] Fix g:black_fast and
g:black_(skip)_string_normalization opts
---
plugin/black.vim | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/plugin/black.vim b/plugin/black.vim
index 4af044e7a68..3dd3f2151c3 100644
--- a/plugin/black.vim
+++ b/plugin/black.vim
@@ -41,8 +41,12 @@ endif
if !exists("g:black_linelength")
let g:black_linelength = 88
endif
-if !exists("g:black_skip_string_normalization")
- let g:black_skip_string_normalization = 0
+if !exists("g:black_string_normalization")
+ if exists("g:black_skip_string_normalization")
+ let g:black_string_normalization = !g:black_skip_string_normalization
+ else
+ let g:black_string_normalization = 1
+ endif
endif
python3 << EndPython3
@@ -50,6 +54,7 @@ import collections
import os
import sys
import vim
+from distutils.util import strtobool
class Flag(collections.namedtuple("FlagBase", "name, cast")):
@@ -62,15 +67,13 @@ class Flag(collections.namedtuple("FlagBase", "name, cast")):
name = self.var_name
if name == "line_length":
name = name.replace("_", "")
- if name == "string_normalization":
- name = "skip_" + name
return "g:black_" + name
FLAGS = [
Flag(name="line_length", cast=int),
- Flag(name="fast", cast=bool),
- Flag(name="string_normalization", cast=bool),
+ Flag(name="fast", cast=strtobool),
+ Flag(name="string_normalization", cast=strtobool),
]
From 7fe19fac5bccc08dbcf21c293ab50f1fcda7716f Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Wed, 26 Aug 2020 18:17:59 -0400
Subject: [PATCH 0006/1034] Fix multiline docstring quote normalization
The quotes of multiline docstrings are now only normalized when string
normalization is off, instead of the string normalization setting being
ignored and the quotes being *always* normalized.
I had to make a new test case and data file since the current pair for
docstrings only worked when there is no formatting difference between the
formatting results with string normalization on and off. I needed to add
tests for when there *are* differences between the two. So I split
test_docstring's test code when string normalization is disabled into a
new test case along with a new data file.
---
CHANGES.md | 7 +
docs/change_log.md | 7 +
src/black/__init__.py | 1 -
.../data/docstring_no_string_normalization.py | 209 ++++++++++++++++++
tests/test_black.py | 13 +-
5 files changed, 232 insertions(+), 5 deletions(-)
create mode 100644 tests/data/docstring_no_string_normalization.py
diff --git a/CHANGES.md b/CHANGES.md
index 11341779f58..7352b857075 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,12 @@
## Change Log
+### Unreleased
+
+#### _Black_
+
+- `Black` now respects `--skip-string-normalization` when normalizing multiline
+ docstring quotes (#1637)
+
### 20.8b1
#### _Packaging_
diff --git a/docs/change_log.md b/docs/change_log.md
index 658414bf967..b7337166659 100644
--- a/docs/change_log.md
+++ b/docs/change_log.md
@@ -2,6 +2,13 @@
## Change Log
+### Unreleased
+
+#### _Black_
+
+- `Black` now respects `--skip-string-normalization` when normalizing multiline
+ docstring quotes (#1637)
+
### 20.8b1
#### _Packaging_
diff --git a/src/black/__init__.py b/src/black/__init__.py
index f51a50d3612..34d8145c0f7 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -2049,7 +2049,6 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
if leaf.value[tail_len + 1] == docstring[-1]:
docstring = docstring + " "
leaf.value = leaf.value[0:lead_len] + docstring + leaf.value[tail_len:]
- normalize_string_quotes(leaf)
yield from self.visit_default(leaf)
diff --git a/tests/data/docstring_no_string_normalization.py b/tests/data/docstring_no_string_normalization.py
new file mode 100644
index 00000000000..0457fcf114f
--- /dev/null
+++ b/tests/data/docstring_no_string_normalization.py
@@ -0,0 +1,209 @@
+class ALonelyClass:
+ '''
+ A multiline class docstring.
+ '''
+ def AnEquallyLonelyMethod(self):
+ '''
+ A multiline method docstring'''
+ pass
+
+
+def one_function():
+ '''This is a docstring with a single line of text.'''
+ pass
+
+
+def shockingly_the_quotes_are_normalized():
+ '''This is a multiline docstring.
+ This is a multiline docstring.
+ This is a multiline docstring.
+ '''
+ pass
+
+
+def foo():
+ """This is a docstring with
+ some lines of text here
+ """
+ return
+
+
+def baz():
+ '''"This" is a string with some
+ embedded "quotes"'''
+ return
+
+
+def poit():
+ """
+ Lorem ipsum dolor sit amet.
+
+ Consectetur adipiscing elit:
+ - sed do eiusmod tempor incididunt ut labore
+ - dolore magna aliqua
+ - enim ad minim veniam
+ - quis nostrud exercitation ullamco laboris nisi
+ - aliquip ex ea commodo consequat
+ """
+ pass
+
+
+def under_indent():
+ """
+ These lines are indented in a way that does not
+make sense.
+ """
+ pass
+
+
+def over_indent():
+ """
+ This has a shallow indent
+ - But some lines are deeper
+ - And the closing quote is too deep
+ """
+ pass
+
+
+def single_line():
+ """But with a newline after it!
+
+ """
+ pass
+
+
+def this():
+ r"""
+ 'hey ho'
+ """
+
+
+def that():
+ """ "hey yah" """
+
+
+def and_that():
+ """
+ "hey yah" """
+
+
+def and_this():
+ '''
+ "hey yah"'''
+
+
+def believe_it_or_not_this_is_in_the_py_stdlib(): '''
+"hey yah"'''
+
+
+def shockingly_the_quotes_are_normalized_v2():
+ '''
+ Docstring Docstring Docstring
+ '''
+ pass
+
+# output
+
+class ALonelyClass:
+ '''
+ A multiline class docstring.
+ '''
+
+ def AnEquallyLonelyMethod(self):
+ '''
+ A multiline method docstring'''
+ pass
+
+
+def one_function():
+ '''This is a docstring with a single line of text.'''
+ pass
+
+
+def shockingly_the_quotes_are_normalized():
+ '''This is a multiline docstring.
+ This is a multiline docstring.
+ This is a multiline docstring.
+ '''
+ pass
+
+
+def foo():
+ """This is a docstring with
+ some lines of text here
+ """
+ return
+
+
+def baz():
+ '''"This" is a string with some
+ embedded "quotes"'''
+ return
+
+
+def poit():
+ """
+ Lorem ipsum dolor sit amet.
+
+ Consectetur adipiscing elit:
+ - sed do eiusmod tempor incididunt ut labore
+ - dolore magna aliqua
+ - enim ad minim veniam
+ - quis nostrud exercitation ullamco laboris nisi
+ - aliquip ex ea commodo consequat
+ """
+ pass
+
+
+def under_indent():
+ """
+ These lines are indented in a way that does not
+ make sense.
+ """
+ pass
+
+
+def over_indent():
+ """
+ This has a shallow indent
+ - But some lines are deeper
+ - And the closing quote is too deep
+ """
+ pass
+
+
+def single_line():
+ """But with a newline after it!"""
+ pass
+
+
+def this():
+ r"""
+ 'hey ho'
+ """
+
+
+def that():
+ """ "hey yah" """
+
+
+def and_that():
+ """
+ "hey yah" """
+
+
+def and_this():
+ '''
+ "hey yah"'''
+
+
+def believe_it_or_not_this_is_in_the_py_stdlib():
+ '''
+ "hey yah"'''
+
+
+def shockingly_the_quotes_are_normalized_v2():
+ '''
+ Docstring Docstring Docstring
+ '''
+ pass
diff --git a/tests/test_black.py b/tests/test_black.py
index f5d4e1115a8..629afc5b0ad 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -517,11 +517,16 @@ def test_docstring(self) -> None:
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, DEFAULT_MODE)
+
+ @patch("black.dump_to_file", dump_to_stderr)
+ def test_docstring_no_string_normalization(self) -> None:
+ """Like test_docstring but with string normalization off."""
+ source, expected = read_data("docstring_no_string_normalization")
mode = replace(DEFAULT_MODE, string_normalization=False)
- not_normalized = fs(source, mode=mode)
- self.assertFormatEqual(expected, not_normalized)
- black.assert_equivalent(source, not_normalized)
- black.assert_stable(source, not_normalized, mode=mode)
+ actual = fs(source, mode=mode)
+ self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(source, actual)
+ black.assert_stable(source, actual, mode)
def test_long_strings(self) -> None:
"""Tests for splitting long strings."""
From 2b75f8870eac943c93e93c740c9d2ef74efeeb41 Mon Sep 17 00:00:00 2001
From: mbarkhau
Date: Thu, 27 Aug 2020 11:47:59 +0000
Subject: [PATCH 0007/1034] fix 1631 and add test (#1641)
---
CHANGES.md | 2 ++
src/black/__init__.py | 3 ++-
tests/test_black.py | 18 ++++++++++++++++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/CHANGES.md b/CHANGES.md
index 7352b857075..1c53604d4d5 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,8 @@
- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)
+- fixed a crash when PWD=/ on POSIX (#1631)
+
### 20.8b1
#### _Packaging_
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 34d8145c0f7..048e771ce96 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -5831,7 +5831,8 @@ def normalize_path_maybe_ignore(
`report` is where "path ignored" output goes.
"""
try:
- normalized_path = path.resolve().relative_to(root).as_posix()
+ abspath = path if path.is_absolute() else Path.cwd() / path
+ normalized_path = abspath.resolve().relative_to(root).as_posix()
except OSError as e:
report.path_ignored(path, f"cannot be read because {e}")
return None
diff --git a/tests/test_black.py b/tests/test_black.py
index 629afc5b0ad..bc80c8fca8b 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -9,6 +9,7 @@
from io import BytesIO, TextIOWrapper
import os
from pathlib import Path
+from platform import system
import regex as re
import sys
from tempfile import TemporaryDirectory
@@ -1939,6 +1940,23 @@ def test_find_project_root(self) -> None:
self.assertEqual(black.find_project_root((src_dir,)), src_dir.resolve())
self.assertEqual(black.find_project_root((src_python,)), src_dir.resolve())
+ def test_bpo_33660_workaround(self) -> None:
+ if system() == "Windows":
+ return
+
+ # https://bugs.python.org/issue33660
+
+ old_cwd = Path.cwd()
+ try:
+ root = Path("/")
+ os.chdir(str(root))
+ path = Path("workspace") / "project"
+ report = black.Report(verbose=True)
+ normalized_path = black.normalize_path_maybe_ignore(path, root, report)
+ self.assertEqual(normalized_path, "workspace/project")
+ finally:
+ os.chdir(str(old_cwd))
+
class BlackDTestCase(AioHTTPTestCase):
async def get_application(self) -> web.Application:
From 0c6d4ca0c33aa97202e0e94a4a2389cc432597bc Mon Sep 17 00:00:00 2001
From: Tristan Seligmann
Date: Fri, 28 Aug 2020 17:37:37 +0200
Subject: [PATCH 0008/1034] Fix typo in comment (#1650)
Co-authored-by: Hugo van Kemenade
---
fuzz.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fuzz.py b/fuzz.py
index fdd4917f2ec..604e6ced291 100644
--- a/fuzz.py
+++ b/fuzz.py
@@ -42,8 +42,8 @@ def test_idempotent_any_syntatically_valid_python(
try:
dst_contents = black.format_str(src_contents, mode=mode)
except black.InvalidInput:
- # This is a bug - if it's valid Python code, as above, black should be
- # able to code with it. See issues #970, #1012, #1358, and #1557.
+ # This is a bug - if it's valid Python code, as above, Black should be
+ # able to cope with it. See issues #970, #1012, #1358, and #1557.
# TODO: remove this try-except block when issues are resolved.
return
From 573b8de54470dbad8bcaaebd5a28dad507c44666 Mon Sep 17 00:00:00 2001
From: Jon Dufresne
Date: Mon, 31 Aug 2020 14:18:43 -0700
Subject: [PATCH 0009/1034] Remove flake8 W503 from docs as it is ignored by
default (#1661)
Fixes #1660
---
.flake8 | 4 ++--
docs/compatible_configs.md | 20 +++++++-------------
docs/the_black_code_style.md | 10 +++-------
3 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/.flake8 b/.flake8
index cee6db4446b..656c0df24ee 100644
--- a/.flake8
+++ b/.flake8
@@ -1,7 +1,7 @@
[flake8]
-ignore = E203, E266, E501, W503
+extend-ignore = E203, E266, E501
# line length is intentionally set to 80 here because black uses Bugbear
-# See https://github.com/psf/black/blob/master/README.md#line-length for more details
+# See https://github.com/psf/black/blob/master/docs/the_black_code_style.md#line-length for more details
max-line-length = 80
max-complexity = 18
select = B,C,E,F,W,T4,B9
diff --git a/docs/compatible_configs.md b/docs/compatible_configs.md
index 25e959e3281..82f13932b0b 100644
--- a/docs/compatible_configs.md
+++ b/docs/compatible_configs.md
@@ -32,7 +32,7 @@ line_length = 88
_Black_ wraps imports that surpass `line-length` by moving identifiers into their own
indented line. If that still doesn't fit the bill, it will put all of them in separate
lines and put a trailing comma. A more detailed explanation of this behaviour can be
-[found here](https://github.com/psf/black#how-black-wraps-lines).
+[found here](https://github.com/psf/black/blob/master/docs/the_black_code_style.md#how-black-wraps-lines).
isort's default mode of wrapping imports that extend past the `line_length` limit is
"Grid".
@@ -146,21 +146,15 @@ There are a few deviations that cause incompatibilities with _Black_.
```
max-line-length = 88
-extend-ignore = E203, W503
+extend-ignore = E203
```
### Why those options above?
-When breaking a line, _Black_ will break it before a binary operator. This is compliant
-with PEP 8, but this behaviour will cause flake8 to raise
-`W503 line break before binary operator` warnings.
-
In some cases, as determined by PEP 8, _Black_ will enforce an equal amount of
whitespace around slice operators. Due to this, Flake8 will raise
-`E203 whitespace before ':'` warnings.
-
-Since both of these warnings are not PEP 8 compliant, Flake8 should be configured to
-ignore these warnings via `extend-ignore = E203, W503`.
+`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, Flake8
+should be configured to ignore it via `extend-ignore = E203`.
Also, as like with isort, flake8 should be configured to allow lines up to the length
limit of `88`, _Black_'s default. This explains `max-line-length = 88`.
@@ -173,7 +167,7 @@ limit of `88`, _Black_'s default. This explains `max-line-length = 88`.
```ini
[flake8]
max-line-length = 88
-extend-ignore = E203, W503
+extend-ignore = E203
```
@@ -184,7 +178,7 @@ extend-ignore = E203, W503
```cfg
[flake8]
max-line-length = 88
-extend-ignore = E203, W503
+extend-ignore = E203
```
@@ -195,7 +189,7 @@ extend-ignore = E203, W503
```ini
[flake8]
max-line-length = 88
-extend-ignore = E203, W503
+extend-ignore = E203
```
diff --git a/docs/the_black_code_style.md b/docs/the_black_code_style.md
index 09d58307a05..735e9c015d7 100644
--- a/docs/the_black_code_style.md
+++ b/docs/the_black_code_style.md
@@ -199,12 +199,12 @@ You'd do it like this:
max-line-length = 80
...
select = C,E,F,W,B,B950
-ignore = E203, E501, W503
+extend-ignore = E203, E501
```
You'll find _Black_'s own .flake8 config file is configured like this. Explanation of
-why W503 and E203 are disabled can be found further in this documentation. And if you're
-curious about the reasoning behind B950,
+why E203 is disabled can be found further in this documentation. And if you're curious
+about the reasoning behind B950,
[Bugbear's documentation](https://github.com/PyCQA/flake8-bugbear#opinionated-warnings)
explains it. The tl;dr is "it's like highway speed limits, we won't bother you if you
overdo it by a few km/h".
@@ -309,10 +309,6 @@ multiple lines. This is so that _Black_ is compliant with the recent changes in
[PEP 8](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
style guide, which emphasizes that this approach improves readability.
-This behaviour may raise `W503 line break before binary operator` warnings in style
-guide enforcement tools like Flake8. Since `W503` is not PEP 8 compliant, you should
-tell Flake8 to ignore these warnings.
-
### Slices
PEP 8
From 1d2d7264ec7c448744b771910cc972da03b1cb80 Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Mon, 31 Aug 2020 17:20:05 -0400
Subject: [PATCH 0010/1034] Fix incorrect space before colon in if/while stmts
(#1655)
* Fix incorrect space before colon in if/while stmts
Previously Black would format this code
```
if (foo := True):
print(foo)
```
as
```
if (foo := True) :
print(foo)
```
adding an incorrect space after the RPAR. Buggy code in the
normalize_invisible_parens function caused the colon to be wrapped in
invisible parentheses. The LPAR of that pair was then prefixed with a
single space at the request of the whitespace function.
This commit fixes the accidental skipping of a pre-condition check
which must return True before parenthesis normalization of a specific
child Leaf or Node can happen. The pre-condition check being skipped
was why the colon was wrapped in invisible parentheses.
* Add an entry in CHANGES.md
---
CHANGES.md | 3 +++
docs/change_log.md | 5 +++++
src/black/__init__.py | 4 ++--
tests/data/pep_572.py | 4 ++++
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 1c53604d4d5..7e356f1f29c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,9 @@
- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)
+- `Black` no longer adds an incorrect space after a parenthesized assignment expression
+ in if/while statements (#1655)
+
- fixed a crash when PWD=/ on POSIX (#1631)
### 20.8b1
diff --git a/docs/change_log.md b/docs/change_log.md
index b7337166659..cc5015f873c 100644
--- a/docs/change_log.md
+++ b/docs/change_log.md
@@ -9,6 +9,11 @@
- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)
+- `Black` no longer adds an incorrect space after a parenthesized assignment expression
+ in if/while statements (#1655)
+
+- fixed a crash when PWD=/ on POSIX (#1631)
+
### 20.8b1
#### _Packaging_
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 048e771ce96..64a18655905 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -5190,9 +5190,9 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
if check_lpar:
if is_walrus_assignment(child):
- continue
+ pass
- if child.type == syms.atom:
+ elif child.type == syms.atom:
if maybe_make_parens_invisible_in_atom(child, parent=node):
wrap_in_parentheses(node, child, visible=False)
elif is_one_tuple(child):
diff --git a/tests/data/pep_572.py b/tests/data/pep_572.py
index 9e429f913ce..637b3bb38c6 100644
--- a/tests/data/pep_572.py
+++ b/tests/data/pep_572.py
@@ -2,6 +2,8 @@
(a := a)
if (match := pattern.search(data)) is None:
pass
+if (match := pattern.search(data)):
+ pass
[y := f(x), y ** 2, y ** 3]
filtered_data = [y for x in data if (y := f(x)) is None]
(y := f(x))
@@ -41,3 +43,5 @@ def foo(answer: (p := 42) = 5):
while x := f(x):
pass
+while (x := f(x)):
+ pass
From 1af648d0c14342021bb8c4220fb8adcd7362d45d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Langa?=
Date: Tue, 1 Sep 2020 13:18:46 +0200
Subject: [PATCH 0011/1034] Mention optional invalid W503 warning in
pycodestyle
---
docs/compatible_configs.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/docs/compatible_configs.md b/docs/compatible_configs.md
index 82f13932b0b..990820a6771 100644
--- a/docs/compatible_configs.md
+++ b/docs/compatible_configs.md
@@ -156,6 +156,13 @@ whitespace around slice operators. Due to this, Flake8 will raise
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, Flake8
should be configured to ignore it via `extend-ignore = E203`.
+When breaking a line, _Black_ will break it before a binary operator. This is compliant
+with PEP 8 as of
+[April 2016](https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b#diff-64ec08cc46db7540f18f2af46037f599).
+There's a disabled-by-default warning in Flake8 which goes against this PEP 8
+recommendation called `W503 line break before binary operator`. It should not be enabled
+in your configuration.
+
Also, as like with isort, flake8 should be configured to allow lines up to the length
limit of `88`, _Black_'s default. This explains `max-line-length = 88`.
From 6b935a34d08c0b18d858e7da5093dc69a29c55f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Langa?=
Date: Tue, 1 Sep 2020 13:24:31 +0200
Subject: [PATCH 0012/1034] Clarify current trailing comma behavior in the docs
---
docs/the_black_code_style.md | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/docs/the_black_code_style.md b/docs/the_black_code_style.md
index 735e9c015d7..19464ba482a 100644
--- a/docs/the_black_code_style.md
+++ b/docs/the_black_code_style.md
@@ -244,16 +244,6 @@ required due to an inner function starting immediately after.
_Black_ will add trailing commas to expressions that are split by comma where each
element is on its own line. This includes function signatures.
-Unnecessary trailing commas are removed if an expression fits in one line. This makes it
-1% more likely that your line won't exceed the allotted line length limit. Moreover, in
-this scenario, if you added another argument to your call, you'd probably fit it in the
-same line anyway. That doesn't make diffs any larger.
-
-One exception to removing trailing commas is tuple expressions with just one element. In
-this case _Black_ won't touch the single trailing comma as this would unexpectedly
-change the underlying data type. Note that this is also the case when commas are used
-while indexing. This is a tuple in disguise: `numpy_array[3, ]`.
-
One exception to adding trailing commas is function signatures containing `*`, `*args`,
or `**kwargs`. In this case a trailing comma is only safe to use on Python 3.6. _Black_
will detect if your file is already 3.6+ only and use trailing commas in this situation.
@@ -262,6 +252,10 @@ in function signatures that have stars in them. In other words, if you'd like a
comma in this situation and _Black_ didn't recognize it was safe to do so, put it there
manually and _Black_ will keep it.
+A pre-existing trailing comma informs _Black_ to always explode contents of the current
+bracket pair into one item per line. Read more about this in the
+[Pragmatism](#pragmatism) section below.
+
### Strings
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
From 25c1b6dff7264278c1ca1649f321a3bd8df293b1 Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Fri, 4 Sep 2020 17:20:55 -0400
Subject: [PATCH 0013/1034] Update primer.json to reflect Black's adoption
(#1674)
- tox recently adopted Black
https://github.com/tox-dev/tox/commit/a7903508fa07068b327e15cfdbf8ea330ab78765
- attrs already adopted Black but they updated to 20.08b1 + did a format pass and removed some trailing commas
https://github.com/python-attrs/attrs/commit/f680c5b83e65413eeb684c68ece60198015058c3
---
src/black_primer/primer.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index 546f47782cd..6371d44ce1f 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -10,7 +10,7 @@
},
"attrs": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/python-attrs/attrs.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -98,7 +98,7 @@
},
"tox": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/tox-dev/tox.git",
"long_checkout": false,
"py_versions": ["all"]
From 17908718338e6ba10d01f3b484ed0fe9542b8169 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade
Date: Sat, 5 Sep 2020 19:38:43 +0300
Subject: [PATCH 0014/1034] Test primer on Pillow (#1679)
---
src/black_primer/primer.json | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index 6371d44ce1f..6086c4c813a 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -61,6 +61,13 @@
"long_checkout": false,
"py_versions": ["all"]
},
+ "pillow": {
+ "cli_arguments": [],
+ "expect_formatting_changes": false,
+ "git_clone_url": "https://github.com/python-pillow/Pillow.git",
+ "long_checkout": false,
+ "py_versions": ["all"]
+ },
"poetry": {
"cli_arguments": [],
"expect_formatting_changes": true,
From 6b5753a41781ef7a8746aeea52c26e07f4b43c27 Mon Sep 17 00:00:00 2001
From: Tom Saunders
Date: Sat, 5 Sep 2020 20:15:28 +0100
Subject: [PATCH 0015/1034] Handle .COLOR_DIFF in the same way as .DIFF (#1673)
---
CHANGES.md | 2 ++
src/black/__init__.py | 6 ++---
tests/test_black.py | 53 ++++++++++++++++++++++++++++++++++++++++---
3 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 7e356f1f29c..52c8016a257 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,8 @@
- fixed a crash when PWD=/ on POSIX (#1631)
+- Prevent coloured diff output being interleaved with multiple files (#1673)
+
### 20.8b1
#### _Packaging_
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 64a18655905..f7e7603321a 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -661,7 +661,7 @@ def reformat_one(
changed = Changed.YES
else:
cache: Cache = {}
- if write_back != WriteBack.DIFF:
+ if write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
cache = read_cache(mode)
res_src = src.resolve()
if res_src in cache and cache[res_src] == get_cache_info(res_src):
@@ -735,7 +735,7 @@ async def schedule_formatting(
:func:`format_file_in_place`.
"""
cache: Cache = {}
- if write_back != WriteBack.DIFF:
+ if write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
cache = read_cache(mode)
sources, cached = filter_cached(cache, sources)
for src in sorted(cached):
@@ -746,7 +746,7 @@ async def schedule_formatting(
cancelled = []
sources_to_cache = []
lock = None
- if write_back == WriteBack.DIFF:
+ if write_back in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
# For diff output, we need locks to ensure we don't interleave output
# from different processes.
manager = Manager()
diff --git a/tests/test_black.py b/tests/test_black.py
index bc80c8fca8b..edcf7208b46 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
+import multiprocessing
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
@@ -1395,9 +1396,55 @@ def test_no_cache_when_writeback_diff(self) -> None:
src = (workspace / "test.py").resolve()
with src.open("w") as fobj:
fobj.write("print('hello')")
- self.invokeBlack([str(src), "--diff"])
- cache_file = black.get_cache_file(mode)
- self.assertFalse(cache_file.exists())
+ with patch("black.read_cache") as read_cache, patch(
+ "black.write_cache"
+ ) as write_cache:
+ self.invokeBlack([str(src), "--diff"])
+ cache_file = black.get_cache_file(mode)
+ self.assertFalse(cache_file.exists())
+ write_cache.assert_not_called()
+ read_cache.assert_not_called()
+
+ def test_no_cache_when_writeback_color_diff(self) -> None:
+ mode = DEFAULT_MODE
+ with cache_dir() as workspace:
+ src = (workspace / "test.py").resolve()
+ with src.open("w") as fobj:
+ fobj.write("print('hello')")
+ with patch("black.read_cache") as read_cache, patch(
+ "black.write_cache"
+ ) as write_cache:
+ self.invokeBlack([str(src), "--diff", "--color"])
+ cache_file = black.get_cache_file(mode)
+ self.assertFalse(cache_file.exists())
+ write_cache.assert_not_called()
+ read_cache.assert_not_called()
+
+ @event_loop()
+ def test_output_locking_when_writeback_diff(self) -> None:
+ with cache_dir() as workspace:
+ for tag in range(0, 4):
+ src = (workspace / f"test{tag}.py").resolve()
+ with src.open("w") as fobj:
+ fobj.write("print('hello')")
+ with patch("black.Manager", wraps=multiprocessing.Manager) as mgr:
+ self.invokeBlack(["--diff", str(workspace)], exit_code=0)
+ # this isn't quite doing what we want, but if it _isn't_
+ # called then we cannot be using the lock it provides
+ mgr.assert_called()
+
+ @event_loop()
+ def test_output_locking_when_writeback_color_diff(self) -> None:
+ with cache_dir() as workspace:
+ for tag in range(0, 4):
+ src = (workspace / f"test{tag}.py").resolve()
+ with src.open("w") as fobj:
+ fobj.write("print('hello')")
+ with patch("black.Manager", wraps=multiprocessing.Manager) as mgr:
+ self.invokeBlack(["--diff", "--color", str(workspace)], exit_code=0)
+ # this isn't quite doing what we want, but if it _isn't_
+ # called then we cannot be using the lock it provides
+ mgr.assert_called()
def test_no_cache_when_stdin(self) -> None:
mode = DEFAULT_MODE
From e3ccabb23c5dc5495bd8f96b5c90c1db6a350d6d Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Sat, 5 Sep 2020 20:24:00 -0400
Subject: [PATCH 0016/1034] Fix unstable formatting on string split + %
formatting (#1680)
Fixes #1595
---
src/black/__init__.py | 2 +-
src/blib2to3/pgen2/pgen.py | 3 +--
tests/data/long_strings.py | 6 ++----
tests/data/long_strings__regression.py | 21 +++++++++++++++++----
4 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index f7e7603321a..eed059e2837 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -2668,9 +2668,9 @@ def rhs(line: Line, features: Collection[Feature]) -> Iterator[Line]:
transformers = [
string_merge,
string_paren_strip,
+ string_split,
delimiter_split,
standalone_comment_split,
- string_split,
string_paren_wrap,
rhs,
]
diff --git a/src/blib2to3/pgen2/pgen.py b/src/blib2to3/pgen2/pgen.py
index 13ec51d1878..a685145933c 100644
--- a/src/blib2to3/pgen2/pgen.py
+++ b/src/blib2to3/pgen2/pgen.py
@@ -168,8 +168,7 @@ def calcfirst(self, name: Text) -> None:
if symbol in inverse:
raise ValueError(
"rule %s is ambiguous; %s is in the first sets of %s as well"
- " as %s"
- % (name, symbol, label, inverse[symbol])
+ " as %s" % (name, symbol, label, inverse[symbol])
)
inverse[symbol] = label
self.first[name] = totalset
diff --git a/tests/data/long_strings.py b/tests/data/long_strings.py
index e1ed90f22de..151396b5239 100644
--- a/tests/data/long_strings.py
+++ b/tests/data/long_strings.py
@@ -380,8 +380,7 @@ def foo():
old_fmt_string1 = (
"While we are on the topic of %s, we should also note that old-style formatting"
- " must also be preserved, since some %s still uses it."
- % ("formatting", "code")
+ " must also be preserved, since some %s still uses it." % ("formatting", "code")
)
old_fmt_string2 = "This is a %s %s %s %s" % (
@@ -448,8 +447,7 @@ def foo():
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to"
- " the AssertionError exception, which uses dynamic string %s."
- % "formatting"
+ " the AssertionError exception, which uses dynamic string %s." % "formatting"
)
assert some_type_of_boolean_expression, (
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 044bb4a5deb..33bf14cfaa3 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -310,6 +310,13 @@ def who(self):
passenger_association=passenger_association,
)
+if __name__ == "__main__":
+ for i in range(4, 8):
+ cmd = (
+ r"for pid in $(ps aux | grep paster | grep -v grep | grep '\-%d' | awk '{print $2}'); do kill $pid; done"
+ % (i)
+ )
+
# output
@@ -435,14 +442,12 @@ def foo():
func_call_where_string_arg_has_old_fmt_and_bad_parens(
"A long string with {}. This string is so long that it is ridiculous. It can't fit"
- " on one line at alllll."
- % "formatting",
+ " on one line at alllll." % "formatting",
)
func_call_where_string_arg_has_old_fmt_and_bad_parens(
"A long string with {}. This {} is so long that it is ridiculous. It can't fit on"
- " one line at alllll."
- % ("formatting", "string"),
+ " one line at alllll." % ("formatting", "string"),
)
@@ -702,3 +707,11 @@ def who(self):
passenger_association=passenger_association,
)
)
+
+
+if __name__ == "__main__":
+ for i in range(4, 8):
+ cmd = (
+ r"for pid in $(ps aux | grep paster | grep -v grep | grep '\-%d' | awk"
+ r" '{print $2}'); do kill $pid; done" % (i)
+ )
From 7bca930ca3d84bbd01e98937b6b8a493d0254c7c Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Sun, 6 Sep 2020 11:02:57 -0400
Subject: [PATCH 0017/1034] Fix crash on concatenated string + comment (fixes
#1596) (#1677)
Co-authored-by: Jelle Zijlstra
---
src/black/__init__.py | 28 +++++++++++++++++++++-----
tests/data/long_strings__regression.py | 27 +++++++++++++++++++++++++
2 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index eed059e2837..ed5256eefe1 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -2889,11 +2889,8 @@ class StringMerger(CustomSplitMapMixin, StringTransformer):
"""StringTransformer that merges strings together.
Requirements:
- (A) The line contains adjacent strings such that at most one substring
- has inline comments AND none of those inline comments are pragmas AND
- the set of all substring prefixes is either of length 1 or equal to
- {"", "f"} AND none of the substrings are raw strings (i.e. are prefixed
- with 'r').
+ (A) The line contains adjacent strings such that ALL of the validation checks
+ listed in StringMerger.__validate_msg(...)'s docstring pass.
OR
(B) The line contains a string which uses line continuation backslashes.
@@ -3142,6 +3139,7 @@ def __validate_msg(line: Line, string_idx: int) -> TResult[None]:
* Ok(None), if ALL validation checks (listed below) pass.
OR
* Err(CannotTransform), if any of the following are true:
+ - The target string group does not contain ANY stand-alone comments.
- The target string is not in a string group (i.e. it has no
adjacent strings).
- The string group has more than one inline comment.
@@ -3150,6 +3148,26 @@ def __validate_msg(line: Line, string_idx: int) -> TResult[None]:
length greater than one and is not equal to {"", "f"}.
- The string group consists of raw strings.
"""
+ # We first check for "inner" stand-alone comments (i.e. stand-alone
+ # comments that have a string leaf before them AND after them).
+ for inc in [1, -1]:
+ i = string_idx
+ found_sa_comment = False
+ is_valid_index = is_valid_index_factory(line.leaves)
+ while is_valid_index(i) and line.leaves[i].type in [
+ token.STRING,
+ STANDALONE_COMMENT,
+ ]:
+ if line.leaves[i].type == STANDALONE_COMMENT:
+ found_sa_comment = True
+ elif found_sa_comment:
+ return TErr(
+ "StringMerger does NOT merge string groups which contain "
+ "stand-alone comments."
+ )
+
+ i += inc
+
num_of_inline_string_comments = 0
set_of_prefixes = set()
num_of_strings = 0
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 33bf14cfaa3..745a636cdcf 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -310,6 +310,19 @@ def who(self):
passenger_association=passenger_association,
)
+xxxxxxx_xxxxxx_xxxxxxx = xxx(
+ [
+ xxxxxxxxxxxx(
+ xxxxxx_xxxxxxx=(
+ '((x.aaaaaaaaa = "xxxxxx.xxxxxxxxxxxxxxxxxxxxx") || (x.xxxxxxxxx = "xxxxxxxxxxxx")) && '
+ # xxxxx xxxxxxxxxxxx xxxx xxx (xxxxxxxxxxxxxxxx) xx x xxxxxxxxx xx xxxxxx.
+ "(x.bbbbbbbbbbbb.xxx != "
+ '"xxx:xxx:xxx::cccccccccccc:xxxxxxx-xxxx/xxxxxxxxxxx/xxxxxxxxxxxxxxxxx") && '
+ )
+ )
+ ]
+)
+
if __name__ == "__main__":
for i in range(4, 8):
cmd = (
@@ -709,6 +722,20 @@ def who(self):
)
+xxxxxxx_xxxxxx_xxxxxxx = xxx(
+ [
+ xxxxxxxxxxxx(
+ xxxxxx_xxxxxxx=(
+ '((x.aaaaaaaaa = "xxxxxx.xxxxxxxxxxxxxxxxxxxxx") || (x.xxxxxxxxx ='
+ ' "xxxxxxxxxxxx")) && '
+ # xxxxx xxxxxxxxxxxx xxxx xxx (xxxxxxxxxxxxxxxx) xx x xxxxxxxxx xx xxxxxx.
+ "(x.bbbbbbbbbbbb.xxx != "
+ '"xxx:xxx:xxx::cccccccccccc:xxxxxxx-xxxx/xxxxxxxxxxx/xxxxxxxxxxxxxxxxx") && '
+ )
+ )
+ ]
+)
+
if __name__ == "__main__":
for i in range(4, 8):
cmd = (
From 6284953d07060804dcdeacf4626b76aed7a20683 Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Sun, 6 Sep 2020 12:15:40 -0400
Subject: [PATCH 0018/1034] Fix crash on assert and parenthesized % format
(fixes #1597, fixes #1605) (#1681)
---
src/black/__init__.py | 27 ++++++++++++++---
tests/data/long_strings__regression.py | 42 ++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index ed5256eefe1..3753d5fca8d 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -112,6 +112,10 @@ class InvalidInput(ValueError):
"""Raised when input source code fails all parse attempts."""
+class BracketMatchError(KeyError):
+ """Raised when an opening bracket is unable to be matched to a closing bracket."""
+
+
T = TypeVar("T")
E = TypeVar("E", bound=Exception)
@@ -1308,7 +1312,13 @@ def mark(self, leaf: Leaf) -> None:
self.maybe_decrement_after_lambda_arguments(leaf)
if leaf.type in CLOSING_BRACKETS:
self.depth -= 1
- opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
+ try:
+ opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
+ except KeyError as e:
+ raise BracketMatchError(
+ "Unable to match a closing bracket to the following opening"
+ f" bracket: {leaf}"
+ ) from e
leaf.opening_bracket = opening_bracket
if not leaf.value:
self.invisible.append(leaf)
@@ -3324,10 +3334,17 @@ def do_transform(self, line: Line, string_idx: int) -> Iterator[TResult[Line]]:
yield TErr(
"Will not strip parentheses which have comments attached to them."
)
+ return
new_line = line.clone()
new_line.comments = line.comments.copy()
- append_leaves(new_line, line, LL[: string_idx - 1])
+ try:
+ append_leaves(new_line, line, LL[: string_idx - 1])
+ except BracketMatchError:
+ # HACK: I believe there is currently a bug somewhere in
+ # right_hand_split() that is causing brackets to not be tracked
+ # properly by a shared BracketTracker.
+ append_leaves(new_line, line, LL[: string_idx - 1], preformatted=True)
string_leaf = Leaf(token.STRING, LL[string_idx].value)
LL[string_idx - 1].remove()
@@ -4598,7 +4615,9 @@ def line_to_string(line: Line) -> str:
return str(line).strip("\n")
-def append_leaves(new_line: Line, old_line: Line, leaves: List[Leaf]) -> None:
+def append_leaves(
+ new_line: Line, old_line: Line, leaves: List[Leaf], preformatted: bool = False
+) -> None:
"""
Append leaves (taken from @old_line) to @new_line, making sure to fix the
underlying Node structure where appropriate.
@@ -4614,7 +4633,7 @@ def append_leaves(new_line: Line, old_line: Line, leaves: List[Leaf]) -> None:
for old_leaf in leaves:
new_leaf = Leaf(old_leaf.type, old_leaf.value)
replace_child(old_leaf, new_leaf)
- new_line.append(new_leaf)
+ new_line.append(new_leaf, preformatted=preformatted)
for comment_leaf in old_line.comments_after(old_leaf):
new_line.append(comment_leaf, preformatted=True)
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 745a636cdcf..1c82613d410 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -330,6 +330,25 @@ def who(self):
% (i)
)
+def A():
+ def B():
+ def C():
+ def D():
+ def E():
+ def F():
+ def G():
+ assert (
+ c_float(val[0][0] / val[0][1]).value
+ == c_float(value[0][0] / value[0][1]).value
+ ), "%s didn't roundtrip" % tag
+
+class xxxxxxxxxxxxxxxxxxxxx(xxxx.xxxxxxxxxxxxx):
+ def xxxxxxx_xxxxxx(xxxx):
+ assert xxxxxxx_xxxx in [
+ x.xxxxx.xxxxxx.xxxxx.xxxxxx,
+ x.xxxxx.xxxxxx.xxxxx.xxxx,
+ ], ("xxxxxxxxxxx xxxxxxx xxxx (xxxxxx xxxx) %x xxx xxxxx" % xxxxxxx_xxxx)
+
# output
@@ -742,3 +761,26 @@ def who(self):
r"for pid in $(ps aux | grep paster | grep -v grep | grep '\-%d' | awk"
r" '{print $2}'); do kill $pid; done" % (i)
)
+
+
+def A():
+ def B():
+ def C():
+ def D():
+ def E():
+ def F():
+ def G():
+ assert (
+ c_float(val[0][0] / val[0][1]).value
+ == c_float(value[0][0] / value[0][1]).value
+ ), "%s didn't roundtrip" % tag
+
+
+class xxxxxxxxxxxxxxxxxxxxx(xxxx.xxxxxxxxxxxxx):
+ def xxxxxxx_xxxxxx(xxxx):
+ assert xxxxxxx_xxxx in [
+ x.xxxxx.xxxxxx.xxxxx.xxxxxx,
+ x.xxxxx.xxxxxx.xxxxx.xxxx,
+ ], (
+ "xxxxxxxxxxx xxxxxxx xxxx (xxxxxx xxxx) %x xxx xxxxx" % xxxxxxx_xxxx
+ )
From 1e8916f450505bfe58649c1ff8c0a3708de47daa Mon Sep 17 00:00:00 2001
From: Michael Wilkinson
Date: Tue, 8 Sep 2020 12:42:57 -0400
Subject: [PATCH 0019/1034] Add link to conda-forge integration (#1687)
* Add link to conda-forge integration
resolves #1686
* README: keep PyPI tags together
Co-authored-by: Hugo van Kemenade
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 20f6fa420b2..942e85444d3 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@
+
From cd055efd7d999421984e8b63afe53b5f9854deb9 Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Thu, 10 Sep 2020 12:24:01 -0400
Subject: [PATCH 0020/1034] Fix unstable subscript assignment string wrapping
(#1678)
Fixes #1598
---
src/black/__init__.py | 7 +++++--
tests/data/long_strings__regression.py | 9 +++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 3753d5fca8d..bfb77126218 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -3507,9 +3507,12 @@ def __get_max_string_length(self, line: Line, string_idx: int) -> int:
# WMA4 a single space.
offset += 1
- # WMA4 the lengths of any leaves that came before that space.
- for leaf in LL[: p_idx + 1]:
+ # WMA4 the lengths of any leaves that came before that space,
+ # but after any closing bracket before that space.
+ for leaf in reversed(LL[: p_idx + 1]):
offset += len(str(leaf))
+ if leaf.type in CLOSING_BRACKETS:
+ break
if is_valid_index(string_idx + 1):
N = LL[string_idx + 1]
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 1c82613d410..8290a4cbc1c 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -349,6 +349,10 @@ def xxxxxxx_xxxxxx(xxxx):
x.xxxxx.xxxxxx.xxxxx.xxxx,
], ("xxxxxxxxxxx xxxxxxx xxxx (xxxxxx xxxx) %x xxx xxxxx" % xxxxxxx_xxxx)
+value.__dict__[
+ key
+] = "test" # set some Thrift field to non-None in the struct aa bb cc dd ee
+
# output
@@ -784,3 +788,8 @@ def xxxxxxx_xxxxxx(xxxx):
], (
"xxxxxxxxxxx xxxxxxx xxxx (xxxxxx xxxx) %x xxx xxxxx" % xxxxxxx_xxxx
)
+
+
+value.__dict__[
+ key
+] = "test" # set some Thrift field to non-None in the struct aa bb cc dd ee
From ecc1f17ee57fd1d6c29e47194b1025721f99455b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade
Date: Thu, 10 Sep 2020 22:52:23 +0300
Subject: [PATCH 0021/1034] Virtualenv is now formatted with newest Black
https://github.com/pypa/virtualenv/pull/1939 (#1695)
---
src/black_primer/primer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index 6086c4c813a..8a90192f27d 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -112,7 +112,7 @@
},
"virtualenv": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/pypa/virtualenv.git",
"long_checkout": false,
"py_versions": ["all"]
From c0a8e4224360a6917dcb5d889b08d5fdcfaf7c2d Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Thu, 10 Sep 2020 16:21:37 -0400
Subject: [PATCH 0022/1034] Fix empty line handling when formatting typing
stubs (#1646)
Black used to erroneously remove all empty lines between non-function
code and decorators when formatting typing stubs. Now a single empty
line is enforced.
I chose for putting empty lines around decorated classes that have empty
bodies since removing empty lines around such classes would cause a
formatting issue that seems to be impossible to fix.
For example:
```
class A: ...
@some_decorator
class B: ...
class C: ...
class D: ...
@some_other_decorator
def foo(): -> None: ...
```
It is easy to enforce no empty lines between class A, B, and C.
Just return 0, 0 for a line that is a decorator and precedes an stub
class. Fortunately before this commit, empty lines after that class
would be removed already.
Now let's look at the empty line between class D and function foo. In
this case, there should be an empty line there since it's class code next
to function code. The problem is that when deciding to add X empty lines
before a decorator, you can't tell whether it's before a class or a
function. If the decorator is before a function, then an empty line
is needed, while no empty lines are needed when the decorator is
before a class.
So even though I personally prefer no empty lines around decorated
classes, I had to go the other way surrounding decorated classes with
empty lines.
Co-authored-by: Jelle Zijlstra
---
CHANGES.md | 3 ++
docs/change_log.md | 3 ++
src/black/__init__.py | 11 +++++--
tests/data/force_pyi.py | 67 ++++++++++++++++++++++++++++++++++++++---
tests/test_black.py | 7 +++--
5 files changed, 82 insertions(+), 9 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 52c8016a257..59d9320639b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,9 @@
- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)
+- `Black` no longer removes all empty lines between non-function code and decorators
+ when formatting typing stubs. Now `Black` enforces a single empty line. (#1646)
+
- `Black` no longer adds an incorrect space after a parenthesized assignment expression
in if/while statements (#1655)
diff --git a/docs/change_log.md b/docs/change_log.md
index cc5015f873c..e183ca545b6 100644
--- a/docs/change_log.md
+++ b/docs/change_log.md
@@ -9,6 +9,9 @@
- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)
+- `Black` no longer removes all empty lines between non-function code and decorators
+ when formatting typing stubs. Now `Black` enforces a single empty line. (#1646)
+
- `Black` no longer adds an incorrect space after a parenthesized assignment expression
in if/while statements (#1655)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index bfb77126218..9e18a7d904b 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -1834,6 +1834,10 @@ def _maybe_empty_lines_for_class_or_def(
return 0, 0
if self.previous_line.is_decorator:
+ if self.is_pyi and current_line.is_stub_class:
+ # Insert an empty line after a decorated stub class
+ return 0, 1
+
return 0, 0
if self.previous_line.depth < current_line.depth and (
@@ -1857,8 +1861,11 @@ def _maybe_empty_lines_for_class_or_def(
newlines = 0
else:
newlines = 1
- elif current_line.is_def and not self.previous_line.is_def:
- # Blank line between a block of functions and a block of non-functions
+ elif (
+ current_line.is_def or current_line.is_decorator
+ ) and not self.previous_line.is_def:
+ # Blank line between a block of functions (maybe with preceding
+ # decorators) and a block of non-functions
newlines = 1
else:
newlines = 0
diff --git a/tests/data/force_pyi.py b/tests/data/force_pyi.py
index 25246c22ca7..07ed93c6879 100644
--- a/tests/data/force_pyi.py
+++ b/tests/data/force_pyi.py
@@ -1,6 +1,65 @@
-def f(): ...
+from typing import Union
+
+@bird
+def zoo(): ...
+
+class A: ...
+@bar
+class B:
+ def BMethod(self) -> None: ...
+ @overload
+ def BMethod(self, arg : List[str]) -> None: ...
+
+class C: ...
+@hmm
+class D: ...
+class E: ...
+
+@baz
+def foo() -> None:
+ ...
+
+class F (A , C): ...
+def spam() -> None: ...
+
+@overload
+def spam(arg: str) -> str: ...
+
+var : int = 1
+
+def eggs() -> Union[str, int]: ...
-def g(): ...
# output
-def f(): ...
-def g(): ...
+
+from typing import Union
+
+@bird
+def zoo(): ...
+
+class A: ...
+
+@bar
+class B:
+ def BMethod(self) -> None: ...
+ @overload
+ def BMethod(self, arg: List[str]) -> None: ...
+
+class C: ...
+
+@hmm
+class D: ...
+
+class E: ...
+
+@baz
+def foo() -> None: ...
+
+class F(A, C): ...
+
+def spam() -> None: ...
+@overload
+def spam(arg: str) -> str: ...
+
+var: int = 1
+
+def eggs() -> Union[str, int]: ...
diff --git a/tests/test_black.py b/tests/test_black.py
index edcf7208b46..e928dc04984 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1574,7 +1574,6 @@ def test_tricky_unicode_symbols(self) -> None:
black.assert_stable(source, actual, DEFAULT_MODE)
def test_single_file_force_pyi(self) -> None:
- reg_mode = DEFAULT_MODE
pyi_mode = replace(DEFAULT_MODE, is_pyi=True)
contents, expected = read_data("force_pyi")
with cache_dir() as workspace:
@@ -1587,9 +1586,11 @@ def test_single_file_force_pyi(self) -> None:
# verify cache with --pyi is separate
pyi_cache = black.read_cache(pyi_mode)
self.assertIn(path, pyi_cache)
- normal_cache = black.read_cache(reg_mode)
+ normal_cache = black.read_cache(DEFAULT_MODE)
self.assertNotIn(path, normal_cache)
- self.assertEqual(actual, expected)
+ self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(contents, actual)
+ black.assert_stable(contents, actual, pyi_mode)
@event_loop()
def test_multi_file_force_pyi(self) -> None:
From 811decd7f10fb2fb3ae343b9d9d0a3ae53b86a53 Mon Sep 17 00:00:00 2001
From: Daniel <61800298+ffe4@users.noreply.github.com>
Date: Sun, 13 Sep 2020 17:59:18 +0200
Subject: [PATCH 0023/1034] Fix typo in docstring (#1700)
Added a missing preposition
---
src/black/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 9e18a7d904b..ffaafe23f9e 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -925,7 +925,7 @@ def format_stdin_to_stdout(
def format_file_contents(src_contents: str, *, fast: bool, mode: Mode) -> FileContent:
- """Reformat contents a file and return new contents.
+ """Reformat contents of a file and return new contents.
If `fast` is False, additionally confirm that the reformatted code is
valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
From 6dddbd72414061cde9dd8ee72eac373b7fcf8b54 Mon Sep 17 00:00:00 2001
From: QuentinSoubeyran <45202794+QuentinSoubeyran@users.noreply.github.com>
Date: Sat, 19 Sep 2020 20:33:10 +0200
Subject: [PATCH 0024/1034] PEP 614 support (#1717)
---
CHANGES.md | 2 +
Pipfile | 2 +-
Pipfile.lock | 297 +++++++++++++++++++++++++--------------
src/black/__init__.py | 70 ++++++++-
src/blib2to3/Grammar.txt | 2 +-
tests/data/decorators.py | 176 +++++++++++++++++++++++
tests/data/python39.py | 37 +++++
tests/test_black.py | 61 +++++++-
8 files changed, 530 insertions(+), 117 deletions(-)
create mode 100644 tests/data/decorators.py
create mode 100644 tests/data/python39.py
diff --git a/CHANGES.md b/CHANGES.md
index 59d9320639b..7ad3482d07a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -17,6 +17,8 @@
- Prevent coloured diff output being interleaved with multiple files (#1673)
+- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+
### 20.8b1
#### _Packaging_
diff --git a/Pipfile b/Pipfile
index 44f57f6773c..1ced1ed096b 100644
--- a/Pipfile
+++ b/Pipfile
@@ -29,7 +29,7 @@ mypy_extensions = ">=0.4.3"
pathspec = ">=0.6"
regex = ">=2020.1.8"
toml = ">=0.10.1"
-typed-ast = "==1.4.0"
+typed-ast = "==1.4.1"
typing_extensions = ">=3.7.4"
black = {editable = true,extras = ["d"],path = "."}
dataclasses = {"python_version <" = "3.7","version >" = "0.6"}
diff --git a/Pipfile.lock b/Pipfile.lock
index 32b8012ff0e..e09d69ea83d 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "61d09a6b8a8c310becd5e108ed08e0eeae50c7323c08c8040367abded0cb1031"
+ "sha256": "46390803c9b9e1b77a1b4a29de602d864dea188488d3aee6361030c91529611c"
},
"pipfile-spec": 6,
"requires": {},
@@ -58,11 +58,11 @@
},
"attrs": {
"hashes": [
- "sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a",
- "sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff"
+ "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
+ "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.1.0"
+ "version": "==20.2.0"
},
"black": {
"editable": true,
@@ -186,39 +186,40 @@
},
"toml": {
"hashes": [
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88",
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
+ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"
],
"index": "pypi",
"version": "==0.10.1"
},
"typed-ast": {
"hashes": [
- "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161",
- "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e",
- "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e",
- "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0",
- "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c",
- "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47",
- "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631",
- "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4",
- "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34",
- "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b",
- "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2",
- "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e",
- "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a",
- "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233",
- "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1",
- "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36",
- "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d",
- "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a",
- "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66",
- "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"index": "pypi",
- "version": "==1.4.0"
+ "version": "==1.4.1"
},
"typing-extensions": {
"hashes": [
@@ -305,11 +306,11 @@
},
"attrs": {
"hashes": [
- "sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a",
- "sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff"
+ "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
+ "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.1.0"
+ "version": "==20.2.0"
},
"babel": {
"hashes": [
@@ -328,11 +329,11 @@
},
"bleach": {
"hashes": [
- "sha256:2bce3d8fab545a6528c8fa5d9f9ae8ebc85a56da365c7f85180bfe96a35ef22f",
- "sha256:3c4c520fdb9db59ef139915a5db79f8b51bc2a7257ea0389f30c846883430a4b"
+ "sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080",
+ "sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==3.1.5"
+ "version": "==3.2.1"
},
"certifi": {
"hashes": [
@@ -341,6 +342,39 @@
],
"version": "==2020.6.20"
},
+ "cffi": {
+ "hashes": [
+ "sha256:0da50dcbccd7cb7e6c741ab7912b2eff48e85af217d72b57f80ebc616257125e",
+ "sha256:12a453e03124069b6896107ee133ae3ab04c624bb10683e1ed1c1663df17c13c",
+ "sha256:15419020b0e812b40d96ec9d369b2bc8109cc3295eac6e013d3261343580cc7e",
+ "sha256:15a5f59a4808f82d8ec7364cbace851df591c2d43bc76bcbe5c4543a7ddd1bf1",
+ "sha256:23e44937d7695c27c66a54d793dd4b45889a81b35c0751ba91040fe825ec59c4",
+ "sha256:29c4688ace466a365b85a51dcc5e3c853c1d283f293dfcc12f7a77e498f160d2",
+ "sha256:57214fa5430399dffd54f4be37b56fe22cedb2b98862550d43cc085fb698dc2c",
+ "sha256:577791f948d34d569acb2d1add5831731c59d5a0c50a6d9f629ae1cefd9ca4a0",
+ "sha256:6539314d84c4d36f28d73adc1b45e9f4ee2a89cdc7e5d2b0a6dbacba31906798",
+ "sha256:65867d63f0fd1b500fa343d7798fa64e9e681b594e0a07dc934c13e76ee28fb1",
+ "sha256:672b539db20fef6b03d6f7a14b5825d57c98e4026401fce838849f8de73fe4d4",
+ "sha256:6843db0343e12e3f52cc58430ad559d850a53684f5b352540ca3f1bc56df0731",
+ "sha256:7057613efefd36cacabbdbcef010e0a9c20a88fc07eb3e616019ea1692fa5df4",
+ "sha256:76ada88d62eb24de7051c5157a1a78fd853cca9b91c0713c2e973e4196271d0c",
+ "sha256:837398c2ec00228679513802e3744d1e8e3cb1204aa6ad408b6aff081e99a487",
+ "sha256:8662aabfeab00cea149a3d1c2999b0731e70c6b5bac596d95d13f643e76d3d4e",
+ "sha256:95e9094162fa712f18b4f60896e34b621df99147c2cee216cfa8f022294e8e9f",
+ "sha256:99cc66b33c418cd579c0f03b77b94263c305c389cb0c6972dac420f24b3bf123",
+ "sha256:9b219511d8b64d3fa14261963933be34028ea0e57455baf6781fe399c2c3206c",
+ "sha256:ae8f34d50af2c2154035984b8b5fc5d9ed63f32fe615646ab435b05b132ca91b",
+ "sha256:b9aa9d8818c2e917fa2c105ad538e222a5bce59777133840b93134022a7ce650",
+ "sha256:bf44a9a0141a082e89c90e8d785b212a872db793a0080c20f6ae6e2a0ebf82ad",
+ "sha256:c0b48b98d79cf795b0916c57bebbc6d16bb43b9fc9b8c9f57f4cf05881904c75",
+ "sha256:da9d3c506f43e220336433dffe643fbfa40096d408cb9b7f2477892f369d5f82",
+ "sha256:e4082d832e36e7f9b2278bc774886ca8207346b99f278e54c9de4834f17232f7",
+ "sha256:e4b9b7af398c32e408c00eb4e0d33ced2f9121fd9fb978e6c1b57edd014a7d15",
+ "sha256:e613514a82539fc48291d01933951a13ae93b6b444a88782480be32245ed4afa",
+ "sha256:f5033952def24172e60493b68717792e3aebb387a8d186c43c020d9363ee7281"
+ ],
+ "version": "==1.14.2"
+ },
"cfgv": {
"hashes": [
"sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d",
@@ -381,43 +415,71 @@
},
"coverage": {
"hashes": [
- "sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb",
- "sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3",
- "sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716",
- "sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034",
- "sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3",
- "sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8",
- "sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0",
- "sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f",
- "sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4",
- "sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962",
- "sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d",
- "sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b",
- "sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4",
- "sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3",
- "sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258",
- "sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59",
- "sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01",
- "sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd",
- "sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b",
- "sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d",
- "sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89",
- "sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd",
- "sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b",
- "sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d",
- "sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46",
- "sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546",
- "sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082",
- "sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b",
- "sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4",
- "sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8",
- "sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811",
- "sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd",
- "sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651",
- "sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0"
- ],
- "index": "pypi",
- "version": "==5.2.1"
+ "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516",
+ "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259",
+ "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9",
+ "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097",
+ "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0",
+ "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f",
+ "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7",
+ "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c",
+ "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5",
+ "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7",
+ "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729",
+ "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978",
+ "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9",
+ "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f",
+ "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9",
+ "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822",
+ "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418",
+ "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82",
+ "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f",
+ "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d",
+ "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221",
+ "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4",
+ "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21",
+ "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709",
+ "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54",
+ "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d",
+ "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270",
+ "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24",
+ "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751",
+ "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a",
+ "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237",
+ "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7",
+ "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636",
+ "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"
+ ],
+ "index": "pypi",
+ "version": "==5.3"
+ },
+ "cryptography": {
+ "hashes": [
+ "sha256:10c9775a3f31610cf6b694d1fe598f2183441de81cedcf1814451ae53d71b13a",
+ "sha256:180c9f855a8ea280e72a5d61cf05681b230c2dce804c48e9b2983f491ecc44ed",
+ "sha256:247df238bc05c7d2e934a761243bfdc67db03f339948b1e2e80c75d41fc7cc36",
+ "sha256:26409a473cc6278e4c90f782cd5968ebad04d3911ed1c402fc86908c17633e08",
+ "sha256:2a27615c965173c4c88f2961cf18115c08fedfb8bdc121347f26e8458dc6d237",
+ "sha256:2e26223ac636ca216e855748e7d435a1bf846809ed12ed898179587d0cf74618",
+ "sha256:321761d55fb7cb256b771ee4ed78e69486a7336be9143b90c52be59d7657f50f",
+ "sha256:4005b38cd86fc51c955db40b0f0e52ff65340874495af72efabb1bb8ca881695",
+ "sha256:4b9e96543d0784acebb70991ebc2dbd99aa287f6217546bb993df22dd361d41c",
+ "sha256:548b0818e88792318dc137d8b1ec82a0ab0af96c7f0603a00bb94f896fbf5e10",
+ "sha256:725875681afe50b41aee7fdd629cedbc4720bab350142b12c55c0a4d17c7416c",
+ "sha256:7a63e97355f3cd77c94bd98c59cb85fe0efd76ea7ef904c9b0316b5bbfde6ed1",
+ "sha256:94191501e4b4009642be21dde2a78bd3c2701a81ee57d3d3d02f1d99f8b64a9e",
+ "sha256:969ae512a250f869c1738ca63be843488ff5cc031987d302c1f59c7dbe1b225f",
+ "sha256:9f734423eb9c2ea85000aa2476e0d7a58e021bc34f0a373ac52a5454cd52f791",
+ "sha256:b45ab1c6ece7c471f01c56f5d19818ca797c34541f0b2351635a5c9fe09ac2e0",
+ "sha256:cc6096c86ec0de26e2263c228fb25ee01c3ff1346d3cfc219d67d49f303585af",
+ "sha256:dc3f437ca6353979aace181f1b790f0fc79e446235b14306241633ab7d61b8f8",
+ "sha256:e7563eb7bc5c7e75a213281715155248cceba88b11cb4b22957ad45b85903761",
+ "sha256:e7dad66a9e5684a40f270bd4aee1906878193ae50a4831922e454a2a457f1716",
+ "sha256:eb80a288e3cfc08f679f95da72d2ef90cb74f6d8a8ba69d2f215c5e110b2ca32",
+ "sha256:fa7fbcc40e2210aca26c7ac8a39467eae444d90a2c346cbcffd9133a166bcc67"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==3.1"
},
"distlib": {
"hashes": [
@@ -468,11 +530,11 @@
},
"identify": {
"hashes": [
- "sha256:9f5fcf22b665eaece583bd395b103c2769772a0f646ffabb5b1f155901b07de2",
- "sha256:b1aa2e05863dc80242610d46a7b49105e2eafe00ef0c8ff311c1828680760c76"
+ "sha256:c770074ae1f19e08aadbda1c886bc6d0cb55ffdc503a8c0fe8699af2fc9664ae",
+ "sha256:d02d004568c5a01261839a05e91705e3e9f5c57a3551648f9b3fb2b9c62c0f62"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.4.29"
+ "version": "==1.5.3"
},
"idna": {
"hashes": [
@@ -490,6 +552,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.2.0"
},
+ "jeepney": {
+ "hashes": [
+ "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e",
+ "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf"
+ ],
+ "markers": "sys_platform == 'linux'",
+ "version": "==0.4.3"
+ },
"jinja2": {
"hashes": [
"sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0",
@@ -500,11 +570,11 @@
},
"keyring": {
"hashes": [
- "sha256:182f94fc0381546489e3e4d90384a8c1d43cc09ffe2eb4a826e7312df6e1be7c",
- "sha256:cd4d486803d55bdb13e2d453eb61dbbc984773e4f2b98a455aa85b1f4bc421e4"
+ "sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d",
+ "sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466"
],
"markers": "python_version >= '3.6'",
- "version": "==21.3.1"
+ "version": "==21.4.0"
},
"markupsafe": {
"hashes": [
@@ -649,6 +719,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.6.0"
},
+ "pycparser": {
+ "hashes": [
+ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
+ "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.20"
+ },
"pyflakes": {
"hashes": [
"sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
@@ -659,11 +737,11 @@
},
"pygments": {
"hashes": [
- "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
- "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"
+ "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998",
+ "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7"
],
"markers": "python_version >= '3.5'",
- "version": "==2.6.1"
+ "version": "==2.7.1"
},
"pyparsing": {
"hashes": [
@@ -761,6 +839,14 @@
],
"version": "==1.4.0"
},
+ "secretstorage": {
+ "hashes": [
+ "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6",
+ "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b"
+ ],
+ "markers": "sys_platform == 'linux'",
+ "version": "==3.1.2"
+ },
"setuptools-scm": {
"hashes": [
"sha256:09c659d1d6680811c43f476a33c6d3d9872416580786e96bd29ea03e6a818e41",
@@ -848,21 +934,21 @@
},
"toml": {
"hashes": [
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88",
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
+ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"
],
"index": "pypi",
"version": "==0.10.1"
},
"tqdm": {
"hashes": [
- "sha256:1a336d2b829be50e46b84668691e0a2719f26c97c62846298dd5ae2937e4d5cf",
- "sha256:564d632ea2b9cb52979f7956e093e831c28d441c11751682f84c86fc46e4fd21"
+ "sha256:8f3c5815e3b5e20bc40463fa6b42a352178859692a68ffaa469706e6d38342a5",
+ "sha256:faf9c671bd3fad5ebaeee366949d969dca2b2be32c872a7092a1e1a9048d105b"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==4.48.2"
+ "version": "==4.49.0"
},
"twine": {
"hashes": [
@@ -874,29 +960,30 @@
},
"typed-ast": {
"hashes": [
- "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161",
- "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e",
- "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e",
- "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0",
- "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c",
- "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47",
- "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631",
- "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4",
- "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34",
- "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b",
- "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2",
- "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e",
- "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a",
- "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233",
- "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1",
- "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36",
- "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d",
- "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a",
- "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66",
- "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"index": "pypi",
- "version": "==1.4.0"
+ "version": "==1.4.1"
},
"typing-extensions": {
"hashes": [
diff --git a/src/black/__init__.py b/src/black/__init__.py
index ffaafe23f9e..c1db8e6ef64 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -178,14 +178,12 @@ class TargetVersion(Enum):
PY36 = 6
PY37 = 7
PY38 = 8
+ PY39 = 9
def is_python2(self) -> bool:
return self is TargetVersion.PY27
-PY36_VERSIONS = {TargetVersion.PY36, TargetVersion.PY37, TargetVersion.PY38}
-
-
class Feature(Enum):
# All string literals are unicode
UNICODE_LITERALS = 1
@@ -199,6 +197,7 @@ class Feature(Enum):
ASYNC_KEYWORDS = 7
ASSIGNMENT_EXPRESSIONS = 8
POS_ONLY_ARGUMENTS = 9
+ RELAXED_DECORATORS = 10
FORCE_OPTIONAL_PARENTHESES = 50
@@ -237,6 +236,17 @@ class Feature(Enum):
Feature.ASSIGNMENT_EXPRESSIONS,
Feature.POS_ONLY_ARGUMENTS,
},
+ TargetVersion.PY39: {
+ Feature.UNICODE_LITERALS,
+ Feature.F_STRINGS,
+ Feature.NUMERIC_UNDERSCORES,
+ Feature.TRAILING_COMMA_IN_CALL,
+ Feature.TRAILING_COMMA_IN_DEF,
+ Feature.ASYNC_KEYWORDS,
+ Feature.ASSIGNMENT_EXPRESSIONS,
+ Feature.RELAXED_DECORATORS,
+ Feature.POS_ONLY_ARGUMENTS,
+ },
}
@@ -2184,6 +2194,9 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901
):
# Python 2 print chevron
return NO
+ elif prevp.type == token.AT and p.parent and p.parent.type == syms.decorator:
+ # no space in decorators
+ return NO
elif prev.type in OPENING_BRACKETS:
return NO
@@ -5499,6 +5512,49 @@ def is_walrus_assignment(node: LN) -> bool:
return inner is not None and inner.type == syms.namedexpr_test
+def is_simple_decorator_trailer(node: LN, last: bool = False) -> bool:
+ """Return True iff `node` is a trailer valid in a simple decorator"""
+ return node.type == syms.trailer and (
+ (
+ len(node.children) == 2
+ and node.children[0].type == token.DOT
+ and node.children[1].type == token.NAME
+ )
+ # last trailer can be arguments
+ or (
+ last
+ and len(node.children) == 3
+ and node.children[0].type == token.LPAR
+ # and node.children[1].type == syms.argument
+ and node.children[2].type == token.RPAR
+ )
+ )
+
+
+def is_simple_decorator_expression(node: LN) -> bool:
+ """Return True iff `node` could be a 'dotted name' decorator
+
+ This function takes the node of the 'namedexpr_test' of the new decorator
+ grammar and test if it would be valid under the old decorator grammar.
+
+ The old grammar was: decorator: @ dotted_name [arguments] NEWLINE
+ The new grammar is : decorator: @ namedexpr_test NEWLINE
+ """
+ if node.type == token.NAME:
+ return True
+ if node.type == syms.power:
+ if node.children:
+ return (
+ node.children[0].type == token.NAME
+ and all(map(is_simple_decorator_trailer, node.children[1:-1]))
+ and (
+ len(node.children) < 2
+ or is_simple_decorator_trailer(node.children[-1], last=True)
+ )
+ )
+ return False
+
+
def is_yield(node: LN) -> bool:
"""Return True if `node` holds a `yield` or `yield from` expression."""
if node.type == syms.yield_expr:
@@ -5684,6 +5740,8 @@ def get_features_used(node: Node) -> Set[Feature]:
- underscores in numeric literals;
- trailing commas after * or ** in function signatures and calls;
- positional only arguments in function signatures and lambdas;
+ - assignment expression;
+ - relaxed decorator syntax;
"""
features: Set[Feature] = set()
for n in node.pre_order():
@@ -5703,6 +5761,12 @@ def get_features_used(node: Node) -> Set[Feature]:
elif n.type == token.COLONEQUAL:
features.add(Feature.ASSIGNMENT_EXPRESSIONS)
+ elif n.type == syms.decorator:
+ if len(n.children) > 1 and not is_simple_decorator_expression(
+ n.children[1]
+ ):
+ features.add(Feature.RELAXED_DECORATORS)
+
elif (
n.type in {syms.typedargslist, syms.arglist}
and n.children
diff --git a/src/blib2to3/Grammar.txt b/src/blib2to3/Grammar.txt
index f14e2b516bd..eafaee84cb3 100644
--- a/src/blib2to3/Grammar.txt
+++ b/src/blib2to3/Grammar.txt
@@ -12,7 +12,7 @@ file_input: (NEWLINE | stmt)* ENDMARKER
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
eval_input: testlist NEWLINE* ENDMARKER
-decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorator: '@' namedexpr_test NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)
async_funcdef: ASYNC funcdef
diff --git a/tests/data/decorators.py b/tests/data/decorators.py
new file mode 100644
index 00000000000..acfad51fcb8
--- /dev/null
+++ b/tests/data/decorators.py
@@ -0,0 +1,176 @@
+# This file doesn't use the standard decomposition.
+# Decorator syntax test cases are separated by double # comments.
+# Those before the 'output' comment are valid under the old syntax.
+# Those after the 'ouput' comment require PEP614 relaxed syntax.
+# Do not remove the double # separator before the first test case, it allows
+# the comment before the test case to be ignored.
+
+##
+
+@decorator
+def f():
+ ...
+
+##
+
+@decorator(arg)
+def f():
+ ...
+
+##
+
+@decorator(kwarg=0)
+def f():
+ ...
+
+##
+
+@decorator(*args)
+def f():
+ ...
+
+##
+
+@decorator(**kwargs)
+def f():
+ ...
+
+##
+
+@decorator(*args, **kwargs)
+def f():
+ ...
+
+##
+
+@decorator(*args, **kwargs,)
+def f():
+ ...
+
+##
+
+@dotted.decorator
+def f():
+ ...
+
+##
+
+@dotted.decorator(arg)
+def f():
+ ...
+
+##
+
+@dotted.decorator(kwarg=0)
+def f():
+ ...
+
+##
+
+@dotted.decorator(*args)
+def f():
+ ...
+
+##
+
+@dotted.decorator(**kwargs)
+def f():
+ ...
+
+##
+
+@dotted.decorator(*args, **kwargs)
+def f():
+ ...
+
+##
+
+@dotted.decorator(*args, **kwargs,)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(arg)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(kwarg=0)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(*args)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(**kwargs)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(*args, **kwargs)
+def f():
+ ...
+
+##
+
+@double.dotted.decorator(*args, **kwargs,)
+def f():
+ ...
+
+##
+
+@_(sequence["decorator"])
+def f():
+ ...
+
+##
+
+@eval("sequence['decorator']")
+def f():
+ ...
+
+# output
+
+##
+
+@decorator()()
+def f():
+ ...
+
+##
+
+@(decorator)
+def f():
+ ...
+
+##
+
+@sequence["decorator"]
+def f():
+ ...
+
+##
+
+@decorator[List[str]]
+def f():
+ ...
+
+##
+
+@var := decorator
+def f():
+ ...
\ No newline at end of file
diff --git a/tests/data/python39.py b/tests/data/python39.py
new file mode 100644
index 00000000000..ae67c2257eb
--- /dev/null
+++ b/tests/data/python39.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3.9
+
+@relaxed_decorator[0]
+def f():
+ ...
+
+@relaxed_decorator[extremely_long_name_that_definitely_will_not_fit_on_one_line_of_standard_length]
+def f():
+ ...
+
+@extremely_long_variable_name_that_doesnt_fit := complex.expression(with_long="arguments_value_that_wont_fit_at_the_end_of_the_line")
+def f():
+ ...
+
+# output
+
+
+#!/usr/bin/env python3.9
+
+
+@relaxed_decorator[0]
+def f():
+ ...
+
+
+@relaxed_decorator[
+ extremely_long_name_that_definitely_will_not_fit_on_one_line_of_standard_length
+]
+def f():
+ ...
+
+
+@extremely_long_variable_name_that_doesnt_fit := complex.expression(
+ with_long="arguments_value_that_wont_fit_at_the_end_of_the_line"
+)
+def f():
+ ...
\ No newline at end of file
diff --git a/tests/test_black.py b/tests/test_black.py
index e928dc04984..e17f43b88d4 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -59,9 +59,13 @@
PROJECT_ROOT = THIS_DIR.parent
DETERMINISTIC_HEADER = "[Deterministic header]"
EMPTY_LINE = "# EMPTY LINE WITH WHITESPACE" + " (this comment will be removed)"
-PY36_ARGS = [
- f"--target-version={version.name.lower()}" for version in black.PY36_VERSIONS
-]
+PY36_VERSIONS = {
+ TargetVersion.PY36,
+ TargetVersion.PY37,
+ TargetVersion.PY38,
+ TargetVersion.PY39,
+}
+PY36_ARGS = [f"--target-version={version.name.lower()}" for version in PY36_VERSIONS]
T = TypeVar("T")
R = TypeVar("R")
@@ -705,7 +709,7 @@ def test_string_prefixes(self) -> None:
@patch("black.dump_to_file", dump_to_stderr)
def test_numeric_literals(self) -> None:
source, expected = read_data("numeric_literals")
- mode = replace(DEFAULT_MODE, target_versions=black.PY36_VERSIONS)
+ mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
actual = fs(source, mode=mode)
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
@@ -714,7 +718,7 @@ def test_numeric_literals(self) -> None:
@patch("black.dump_to_file", dump_to_stderr)
def test_numeric_literals_ignoring_underscores(self) -> None:
source, expected = read_data("numeric_literals_skip_underscores")
- mode = replace(DEFAULT_MODE, target_versions=black.PY36_VERSIONS)
+ mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
actual = fs(source, mode=mode)
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
@@ -800,6 +804,16 @@ def test_python38(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, DEFAULT_MODE)
+ @patch("black.dump_to_file", dump_to_stderr)
+ def test_python39(self) -> None:
+ source, expected = read_data("python39")
+ actual = fs(source)
+ self.assertFormatEqual(expected, actual)
+ major, minor = sys.version_info[:2]
+ if major > 3 or (major == 3 and minor >= 9):
+ black.assert_equivalent(source, actual)
+ black.assert_stable(source, actual, DEFAULT_MODE)
+
@patch("black.dump_to_file", dump_to_stderr)
def test_fmtonoff(self) -> None:
source, expected = read_data("fmtonoff")
@@ -1212,6 +1226,39 @@ def test_lib2to3_parse(self) -> None:
black.lib2to3_parse(py3_only, {TargetVersion.PY36})
black.lib2to3_parse(py3_only, {TargetVersion.PY27, TargetVersion.PY36})
+ def test_get_features_used_decorator(self) -> None:
+ # Test the feature detection of new decorator syntax
+ # since this makes some test cases of test_get_features_used()
+ # fails if it fails, this is tested first so that a useful case
+ # is identified
+ simples, relaxed = read_data("decorators")
+ # skip explanation comments at the top of the file
+ for simple_test in simples.split("##")[1:]:
+ node = black.lib2to3_parse(simple_test)
+ decorator = str(node.children[0].children[0]).strip()
+ self.assertNotIn(
+ Feature.RELAXED_DECORATORS,
+ black.get_features_used(node),
+ msg=(
+ f"decorator '{decorator}' follows python<=3.8 syntax"
+ "but is detected as 3.9+"
+ # f"The full node is\n{node!r}"
+ ),
+ )
+ # skip the '# output' comment at the top of the output part
+ for relaxed_test in relaxed.split("##")[1:]:
+ node = black.lib2to3_parse(relaxed_test)
+ decorator = str(node.children[0].children[0]).strip()
+ self.assertIn(
+ Feature.RELAXED_DECORATORS,
+ black.get_features_used(node),
+ msg=(
+ f"decorator '{decorator}' uses python3.9+ syntax"
+ "but is detected as python<=3.8"
+ # f"The full node is\n{node!r}"
+ ),
+ )
+
def test_get_features_used(self) -> None:
node = black.lib2to3_parse("def f(*, arg): ...\n")
self.assertEqual(black.get_features_used(node), set())
@@ -1628,7 +1675,7 @@ def test_pipe_force_pyi(self) -> None:
def test_single_file_force_py36(self) -> None:
reg_mode = DEFAULT_MODE
- py36_mode = replace(DEFAULT_MODE, target_versions=black.PY36_VERSIONS)
+ py36_mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
source, expected = read_data("force_py36")
with cache_dir() as workspace:
path = (workspace / "file.py").resolve()
@@ -1647,7 +1694,7 @@ def test_single_file_force_py36(self) -> None:
@event_loop()
def test_multi_file_force_py36(self) -> None:
reg_mode = DEFAULT_MODE
- py36_mode = replace(DEFAULT_MODE, target_versions=black.PY36_VERSIONS)
+ py36_mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
source, expected = read_data("force_py36")
with cache_dir() as workspace:
paths = [
From bc138d12630ec38cb1b11b2fb2ca8762ac2ae7a4 Mon Sep 17 00:00:00 2001
From: Vipul
Date: Sun, 27 Sep 2020 05:54:21 +0000
Subject: [PATCH 0025/1034] End 'force-exclude' help message with a period
(#1727)
It would be nice, if like other options help message, force-exclude's
help message also ends with a period punctuation mark.
---
README.md | 2 +-
docs/installation_and_usage.md | 2 +-
src/black/__init__.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 942e85444d3..aef850f1415 100644
--- a/README.md
+++ b/README.md
@@ -133,7 +133,7 @@ Options:
--force-exclude TEXT Like --exclude, but files and directories
matching this regex will be excluded even
- when they are passed explicitly as arguments
+ when they are passed explicitly as arguments.
-q, --quiet Don't emit non-error messages to stderr.
Errors are still emitted; silence those with
diff --git a/docs/installation_and_usage.md b/docs/installation_and_usage.md
index cc0269198a2..7d37f59264b 100644
--- a/docs/installation_and_usage.md
+++ b/docs/installation_and_usage.md
@@ -88,7 +88,7 @@ Options:
--force-exclude TEXT Like --exclude, but files and directories
matching this regex will be excluded even
- when they are passed explicitly as arguments
+ when they are passed explicitly as arguments.
-q, --quiet Don't emit non-error messages to stderr.
Errors are still emitted; silence those with
diff --git a/src/black/__init__.py b/src/black/__init__.py
index c1db8e6ef64..dce7a24445a 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -454,7 +454,7 @@ def target_version_option_callback(
type=str,
help=(
"Like --exclude, but files and directories matching this regex will be "
- "excluded even when they are passed explicitly as arguments"
+ "excluded even when they are passed explicitly as arguments."
),
)
@click.option(
From 4d71d74a442ccc6c309a0667147997c1eeb755fd Mon Sep 17 00:00:00 2001
From: Pete Grayson
Date: Sun, 27 Sep 2020 21:41:11 +0000
Subject: [PATCH 0026/1034] Repair colorama wrapping on non-Windows platforms
(#1670)
* Repair colorama wrapping on non-Windows platforms
The wrap_stream_for_windows() function calls
colorama.initialise.wrap_stream() function to apply colorama's magic to
wrapper to the output stream. Except this wrapper is only applied on
Windows platforms that need it, otherwise the original stream is
returned as-is.
The colorama wrapped stream lacks a detach() method, so a no-op lambda
was being assigned to the wrapped stream.
The problem is that the no-op lambda was being assigned unconditionally
whether or not colorama actually returns a wrapped stream, thus
replacing the original TextIOWrapper's detach() method. Replacing the
detach() method with a no-op lambda is the root cause of the problem
observed in #1664.
The solution is to only assign the no-op detach() method if the stream
lacks its own detach() method.
Repairs #1664
---
CHANGES.md | 2 ++
README.md | 1 +
src/black/__init__.py | 30 +++++++++++-------------------
3 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 7ad3482d07a..dfc54224b41 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -15,6 +15,8 @@
- fixed a crash when PWD=/ on POSIX (#1631)
+- fixed "I/O operation on closed file" when using --diff (#1664)
+
- Prevent coloured diff output being interleaved with multiple files (#1673)
- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
diff --git a/README.md b/README.md
index aef850f1415..f17b353b023 100644
--- a/README.md
+++ b/README.md
@@ -636,6 +636,7 @@ Multiple contributions by:
- [Paul Ganssle](mailto:p.ganssle@gmail.com)
- [Paul Meinhardt](mailto:mnhrdt@gmail.com)
- [Peter Bengtsson](mailto:mail@peterbe.com)
+- [Peter Grayson](mailto:pete@jpgrayson.net)
- [Peter Stensmyr](mailto:peter.stensmyr@gmail.com)
- pmacosta
- [Quentin Pradet](mailto:quentin@pradet.me)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index dce7a24445a..9af58014c51 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -871,30 +871,22 @@ def color_diff(contents: str) -> str:
def wrap_stream_for_windows(
f: io.TextIOWrapper,
-) -> Union[io.TextIOWrapper, "colorama.AnsiToWin32.AnsiToWin32"]:
+) -> Union[io.TextIOWrapper, "colorama.AnsiToWin32"]:
"""
- Wrap the stream in colorama's wrap_stream so colors are shown on Windows.
+ Wrap stream with colorama's wrap_stream so colors are shown on Windows.
- If `colorama` is not found, then no change is made. If `colorama` does
- exist, then it handles the logic to determine whether or not to change
- things.
+ If `colorama` is unavailable, the original stream is returned unmodified.
+ Otherwise, the `wrap_stream()` function determines whether the stream needs
+ to be wrapped for a Windows environment and will accordingly either return
+ an `AnsiToWin32` wrapper or the original stream.
"""
try:
- from colorama import initialise
-
- # We set `strip=False` so that we can don't have to modify
- # test_express_diff_with_color.
- f = initialise.wrap_stream(
- f, convert=None, strip=False, autoreset=False, wrap=True
- )
-
- # wrap_stream returns a `colorama.AnsiToWin32.AnsiToWin32` object
- # which does not have a `detach()` method. So we fake one.
- f.detach = lambda *args, **kwargs: None # type: ignore
+ from colorama.initialise import wrap_stream
except ImportError:
- pass
-
- return f
+ return f
+ else:
+ # Set `strip=False` to avoid needing to modify test_express_diff_with_color.
+ return wrap_stream(f, convert=None, strip=False, autoreset=False, wrap=True)
def format_stdin_to_stdout(
From 82c1f871d07e9c6334b5fb0bf089273a08ffd195 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade
Date: Mon, 28 Sep 2020 05:42:01 +0300
Subject: [PATCH 0027/1034] Hypothesis is now formatted with Black 20.8b1
(#1729)
---
src/black_primer/primer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index 8a90192f27d..5818444e632 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -47,7 +47,7 @@
},
"hypothesis": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/HypothesisWorks/hypothesis.git",
"long_checkout": false,
"py_versions": ["all"]
From 172c0a78facd8f938629f216c95507bbfeddfe5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hakan=20=C3=87elik?=
Date: Mon, 28 Sep 2020 22:55:35 +0300
Subject: [PATCH 0028/1034] Fix unnecessary if checks (#1728)
---
src/black/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 9af58014c51..24e9d4edaaa 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -859,9 +859,9 @@ def color_diff(contents: str) -> str:
for i, line in enumerate(lines):
if line.startswith("+++") or line.startswith("---"):
line = "\033[1;37m" + line + "\033[0m" # bold white, reset
- if line.startswith("@@"):
+ elif line.startswith("@@"):
line = "\033[36m" + line + "\033[0m" # cyan, reset
- if line.startswith("+"):
+ elif line.startswith("+"):
line = "\033[32m" + line + "\033[0m" # green, reset
elif line.startswith("-"):
line = "\033[31m" + line + "\033[0m" # red, reset
From 283d999c3f89e2204cbf5a61242665bedd6887ef Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade
Date: Fri, 2 Oct 2020 14:47:57 +0300
Subject: [PATCH 0029/1034] Primer: pyramid and sqlalchemy are now formatted
with latest Black (#1736)
---
src/black_primer/primer.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index 5818444e632..cdc863ca032 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -77,7 +77,7 @@
},
"pyramid": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/Pylons/pyramid.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -98,7 +98,7 @@
},
"sqlalchemy": {
"cli_arguments": [],
- "expect_formatting_changes": true,
+ "expect_formatting_changes": false,
"git_clone_url": "https://github.com/sqlalchemy/sqlalchemy.git",
"long_checkout": false,
"py_versions": ["all"]
From d9884b6d330d56b2d2ea1d24f1bdf36ff433c0e6 Mon Sep 17 00:00:00 2001
From: Cha Gyuseok
Date: Wed, 7 Oct 2020 23:45:06 +0900
Subject: [PATCH 0030/1034] docs: update `used-by` link to proper url (#1745)
---
README.md | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index f17b353b023..9c10a63fe29 100644
--- a/README.md
+++ b/README.md
@@ -212,12 +212,13 @@ know!)
### NOTE: This is a beta product
-_Black_ is already [successfully used](#used-by) by many projects, small and big. It
-also sports a decent test suite. However, it is still very new. Things will probably be
-wonky for a while. This is made explicit by the "Beta" trove classifier, as well as by
-the "b" in the version number. What this means for you is that **until the formatter
-becomes stable, you should expect some formatting to change in the future**. That being
-said, no drastic stylistic changes are planned, mostly responses to bug reports.
+_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
+projects, small and big. It also sports a decent test suite. However, it is still very
+new. Things will probably be wonky for a while. This is made explicit by the "Beta"
+trove classifier, as well as by the "b" in the version number. What this means for you
+is that **until the formatter becomes stable, you should expect some formatting to
+change in the future**. That being said, no drastic stylistic changes are planned,
+mostly responses to bug reports.
Also, as a temporary safety measure, _Black_ will check that the reformatted code still
produces a valid AST that is equivalent to the original. This slows it down. If you're
From dd2f86ac0a043815821d228b9db036a295be5372 Mon Sep 17 00:00:00 2001
From: Hadi Alqattan
Date: Fri, 9 Oct 2020 00:13:13 +0300
Subject: [PATCH 0031/1034] Support stable Python3.9. (#1748)
* Support stable Python3.9.
* Get back to 3.9-dev
* Add py39 to black usage.
* remove 3.9 temporarily.
---
.github/workflows/doc.yml | 4 ++--
.github/workflows/fuzz.yml | 2 +-
.github/workflows/primer.yml | 2 +-
.github/workflows/test.yml | 2 +-
CONTRIBUTING.md | 2 +-
README.md | 2 +-
docs/contributing_to_black.md | 2 +-
docs/installation_and_usage.md | 2 +-
readthedocs.yml | 2 +-
setup.py | 1 +
10 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml
index 6023a02a7f7..d266e55aa02 100644
--- a/.github/workflows/doc.yml
+++ b/.github/workflows/doc.yml
@@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Set up Python 3.8
+ - name: Set up Python 3.9
uses: actions/setup-python@v2
with:
- python-version: 3.8
+ python-version: 3.9
- name: Install dependencies
run: |
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 92caa0fd5c1..9aec3c08c63 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [3.6, 3.7, 3.8]
+ python-version: [3.6, 3.7, 3.8] # Python3.9 should be added after fixing [https://github.com/Zac-HD/hypothesmith/issues/11].
steps:
- uses: actions/checkout@v2
diff --git a/.github/workflows/primer.yml b/.github/workflows/primer.yml
index 9b10db0d285..b623b938345 100644
--- a/.github/workflows/primer.yml
+++ b/.github/workflows/primer.yml
@@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [3.6, 3.7, 3.8]
+ python-version: [3.6, 3.7, 3.8, 3.9]
os: [ubuntu-latest, windows-latest]
steps:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index bd0af61e7f5..e30a8b8eb68 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [3.6, 3.7, 3.8]
+ python-version: [3.6, 3.7, 3.8, 3.9]
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0687aaeee52..d446e6a0806 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,7 +19,7 @@ unlikely to get accepted. You can still try but prepare to be disappointed.
## Technicalities
-Development on the latest version of Python is preferred. As of this writing it's 3.8.
+Development on the latest version of Python is preferred. As of this writing it's 3.9.
You can use any operating system. I am using macOS myself and CentOS at work.
Install all development dependencies using:
diff --git a/README.md b/README.md
index 9c10a63fe29..2ca76dd6415 100644
--- a/README.md
+++ b/README.md
@@ -86,7 +86,7 @@ Options:
-l, --line-length INTEGER How many characters per line to allow.
[default: 88]
- -t, --target-version [py27|py33|py34|py35|py36|py37|py38]
+ -t, --target-version [py27|py33|py34|py35|py36|py37|py38|py39]
Python versions that should be supported by
Black's output. [default: per-file auto-
detection]
diff --git a/docs/contributing_to_black.md b/docs/contributing_to_black.md
index e5307adb5d0..8e332993f97 100644
--- a/docs/contributing_to_black.md
+++ b/docs/contributing_to_black.md
@@ -21,7 +21,7 @@ unlikely to get accepted. You can still try but prepare to be disappointed.
## Technicalities
-Development on the latest version of Python is preferred. As of this writing it's 3.8.
+Development on the latest version of Python is preferred. As of this writing it's 3.9.
You can use any operating system. I am using macOS myself and CentOS at work.
Install all development dependencies using:
diff --git a/docs/installation_and_usage.md b/docs/installation_and_usage.md
index 7d37f59264b..7de8b657adf 100644
--- a/docs/installation_and_usage.md
+++ b/docs/installation_and_usage.md
@@ -41,7 +41,7 @@ Options:
-l, --line-length INTEGER How many characters per line to allow.
[default: 88]
- -t, --target-version [py27|py33|py34|py35|py36|py37|py38]
+ -t, --target-version [py27|py33|py34|py35|py36|py37|py38|py39]
Python versions that should be supported by
Black's output. [default: per-file auto-
detection]
diff --git a/readthedocs.yml b/readthedocs.yml
index 15065033d0f..32bcf1fa50e 100644
--- a/readthedocs.yml
+++ b/readthedocs.yml
@@ -1,6 +1,6 @@
version: 2
python:
- version: 3.8
+ version: 3.9
install:
- requirements: docs/requirements.txt
- method: setuptools
diff --git a/setup.py b/setup.py
index 12fde2568cf..14bc1ef586a 100644
--- a/setup.py
+++ b/setup.py
@@ -93,6 +93,7 @@ def get_long_description() -> str:
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
From f311d82569b9595d85c08cc8fcf5250de525e7a0 Mon Sep 17 00:00:00 2001
From: Cooper Lees
Date: Mon, 12 Oct 2020 22:03:00 -0700
Subject: [PATCH 0032/1034] Add blackd to nicely exit if missing aiohttp deps
(#1761)
- If no aiohttp* deps exist nicely print a helpful message and exit
- There seems to be no nice way to optionally install the entry point, so lets make the entry point nicer
Test:
```
cooper-mbp1:black cooper$ /tmp/tb/bin/pip install .
cooper-mbp1:black cooper$ /tmp/tb/bin/blackd
aiohttp dependency is not installed: No module named 'aiohttp'. Please re-install black with the '[d]' extra install to obtain aiohttp_cors: `pip install black[d]`
cooper-mbp1:black cooper$ /tmp/tb/bin/pip install .[d]
...
Successfully installed aiohttp-3.6.3 aiohttp-cors-0.7.0 black
cooper-mbp1:black cooper$ /tmp/tb/bin/blackd
blackd version 20.8b2.dev31+gdd2f86a.d20201013 listening on localhost port 45484
```
Fixes #1688
---
src/blackd/__init__.py | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/blackd/__init__.py b/src/blackd/__init__.py
index d79bfe75bc2..f77a5e8e7be 100644
--- a/src/blackd/__init__.py
+++ b/src/blackd/__init__.py
@@ -1,13 +1,24 @@
import asyncio
+import logging
+import sys
from concurrent.futures import Executor, ProcessPoolExecutor
from datetime import datetime
from functools import partial
-import logging
from multiprocessing import freeze_support
from typing import Set, Tuple
-from aiohttp import web
-import aiohttp_cors
+try:
+ from aiohttp import web
+ import aiohttp_cors
+except ImportError as ie:
+ print(
+ f"aiohttp dependency is not installed: {ie}. "
+ + "Please re-install black with the '[d]' extra install "
+ + "to obtain aiohttp_cors: `pip install black[d]`",
+ file=sys.stderr,
+ )
+ sys.exit(-1)
+
import black
import click
From 4d6a84a8294d035747404d00b88a925fc2640e1e Mon Sep 17 00:00:00 2001
From: Hadi Alqattan
Date: Mon, 19 Oct 2020 00:24:33 +0300
Subject: [PATCH 0033/1034] Allow black's Github action params overriding.
(#1755)
* Allow default params overriding.
* Update: docs and action.yaml.
* The second contirbution, add my name to authors.md
* Correct docs `with.args` example.
* Just to rerun the Travis jobs.
* chmod 755
---
README.md | 1 +
action.yml | 2 +-
Dockerfile => action/Dockerfile | 4 +++-
action/entrypoint.sh | 10 ++++++++++
docs/authors.md | 1 +
docs/github_actions.md | 4 +++-
6 files changed, 19 insertions(+), 3 deletions(-)
rename Dockerfile => action/Dockerfile (64%)
create mode 100755 action/entrypoint.sh
diff --git a/README.md b/README.md
index 2ca76dd6415..7cd4d7f13b2 100644
--- a/README.md
+++ b/README.md
@@ -574,6 +574,7 @@ Multiple contributions by:
- [Gregory P. Smith](mailto:greg@krypto.org)
- Gustavo Camargo
- hauntsaninja
+- [Hadi Alqattan](mailto:alqattanhadizaki@gmail.com)
- [Heaford](mailto:dan@heaford.com)
- [Hugo Barrera](mailto::hugo@barrera.io)
- Hugo van Kemenade
diff --git a/action.yml b/action.yml
index 2ce1c0bf2ef..60bf369a3d8 100644
--- a/action.yml
+++ b/action.yml
@@ -6,4 +6,4 @@ branding:
icon: "check-circle"
runs:
using: "docker"
- image: "Dockerfile"
+ image: "action/Dockerfile"
diff --git a/Dockerfile b/action/Dockerfile
similarity index 64%
rename from Dockerfile
rename to action/Dockerfile
index a03d23a1078..eb2209940db 100644
--- a/Dockerfile
+++ b/action/Dockerfile
@@ -5,4 +5,6 @@ ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade --no-cache-dir black
-ENTRYPOINT /usr/local/bin/black --check --diff .
+COPY entrypoint.sh /entrypoint.sh
+
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/action/entrypoint.sh b/action/entrypoint.sh
new file mode 100755
index 00000000000..dc86fa1996e
--- /dev/null
+++ b/action/entrypoint.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -e
+
+if [ $# -eq 0 ]; then
+ # Default (if no args provided).
+ sh -c "black . --check --diff"
+else
+ # Custom args.
+ sh -c "black $*"
+fi
diff --git a/docs/authors.md b/docs/authors.md
index a5349b4b9df..ebf64eaae76 100644
--- a/docs/authors.md
+++ b/docs/authors.md
@@ -69,6 +69,7 @@ Multiple contributions by:
- [Gregory P. Smith](mailto:greg@krypto.org)
- Gustavo Camargo
- hauntsaninja
+- [Hadi Alqattan](mailto:alqattanhadizaki@gmail.com)
- [Heaford](mailto:dan@heaford.com)
- [Hugo Barrera](mailto::hugo@barrera.io)
- Hugo van Kemenade
diff --git a/docs/github_actions.md b/docs/github_actions.md
index 7ff87540242..ac80c2fab6f 100644
--- a/docs/github_actions.md
+++ b/docs/github_actions.md
@@ -15,5 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- - uses: psf/black@stable
+ - uses: psf/black@stable # the default is equivalent to `black . --diff --check`.
+ with: # (optional - override the default parameters).
+ args: ". --diff --check"
```
From 3e3da8eef6f4ba48da1505ad68ca0e1d788f6d6b Mon Sep 17 00:00:00 2001
From: "David W.H. Swenson"
Date: Sun, 18 Oct 2020 23:27:15 +0200
Subject: [PATCH 0034/1034] Fix GitHub markdown links to work on RTD (#1752)
* Fix internal links to work on RTD
Note that these still lead to GitHub, instead of staying on RTD.
* Point links to better anchors
---
CONTRIBUTING.md | 2 +-
README.md | 2 +-
docs/authors.md | 1 +
docs/change_log.md | 6 ++++++
docs/contributing_to_black.md | 2 +-
docs/installation_and_usage.md | 15 ++++++++-------
6 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d446e6a0806..a4250f78718 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -52,7 +52,7 @@ your PR. You may need to change
configuration for it to pass.
For more `black-primer` information visit the
-[documentation](https://github.com/psf/black/blob/master/docs/black_primer.md).
+[documentation](https://github.com/psf/black/blob/master/docs/black_primer.md#black-primer).
## Hygiene
diff --git a/README.md b/README.md
index 7cd4d7f13b2..47472810114 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,7 @@ about _Black_'s changes or will overwrite _Black_'s changes. A good example of t
should be configured to neither warn about nor overwrite _Black_'s changes.
Actual details on _Black_ compatible configurations for various tools can be found in
-[compatible_configs](https://github.com/psf/black/blob/master/docs/compatible_configs.md).
+[compatible_configs](https://github.com/psf/black/blob/master/docs/compatible_configs.md#black-compatible-configurations).
### Migrating your code style without ruining git blame
diff --git a/docs/authors.md b/docs/authors.md
index ebf64eaae76..cdf5046c446 100644
--- a/docs/authors.md
+++ b/docs/authors.md
@@ -133,6 +133,7 @@ Multiple contributions by:
- [Paul Ganssle](mailto:p.ganssle@gmail.com)
- [Paul Meinhardt](mailto:mnhrdt@gmail.com)
- [Peter Bengtsson](mailto:mail@peterbe.com)
+- [Peter Grayson](mailto:pete@jpgrayson.net)
- [Peter Stensmyr](mailto:peter.stensmyr@gmail.com)
- pmacosta
- [Quentin Pradet](mailto:quentin@pradet.me)
diff --git a/docs/change_log.md b/docs/change_log.md
index e183ca545b6..1ee35a4d8f9 100644
--- a/docs/change_log.md
+++ b/docs/change_log.md
@@ -17,6 +17,12 @@
- fixed a crash when PWD=/ on POSIX (#1631)
+- fixed "I/O operation on closed file" when using --diff (#1664)
+
+- Prevent coloured diff output being interleaved with multiple files (#1673)
+
+- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+
### 20.8b1
#### _Packaging_
diff --git a/docs/contributing_to_black.md b/docs/contributing_to_black.md
index 8e332993f97..f0be872a578 100644
--- a/docs/contributing_to_black.md
+++ b/docs/contributing_to_black.md
@@ -54,7 +54,7 @@ your PR. You may need to change
configuration for it to pass.
For more `black-primer` information visit the
-[documentation](https://github.com/psf/black/blob/master/docs/black_primer.md).
+[documentation](https://github.com/psf/black/blob/master/docs/black_primer.md#).
## Hygiene
diff --git a/docs/installation_and_usage.md b/docs/installation_and_usage.md
index 7de8b657adf..c91a1c400ef 100644
--- a/docs/installation_and_usage.md
+++ b/docs/installation_and_usage.md
@@ -119,7 +119,7 @@ about _Black_'s changes or will overwrite _Black_'s changes. A good example of t
should be configured to neither warn about nor overwrite _Black_'s changes.
Actual details on _Black_ compatible configurations for various tools can be found in
-[compatible_configs](https://github.com/psf/black/blob/master/docs/compatible_configs.md).
+[compatible_configs](https://github.com/psf/black/blob/master/docs/compatible_configs.md#).
## Migrating your code style without ruining git blame
@@ -167,12 +167,13 @@ know!)
## NOTE: This is a beta product
-_Black_ is already [successfully used](#used-by) by many projects, small and big. It
-also sports a decent test suite. However, it is still very new. Things will probably be
-wonky for a while. This is made explicit by the "Beta" trove classifier, as well as by
-the "b" in the version number. What this means for you is that **until the formatter
-becomes stable, you should expect some formatting to change in the future**. That being
-said, no drastic stylistic changes are planned, mostly responses to bug reports.
+_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
+projects, small and big. It also sports a decent test suite. However, it is still very
+new. Things will probably be wonky for a while. This is made explicit by the "Beta"
+trove classifier, as well as by the "b" in the version number. What this means for you
+is that **until the formatter becomes stable, you should expect some formatting to
+change in the future**. That being said, no drastic stylistic changes are planned,
+mostly responses to bug reports.
Also, as a temporary safety measure, _Black_ will check that the reformatted code still
produces a valid AST that is equivalent to the original. This slows it down. If you're
From 3be0aa71d9e39a8fdb6f38cc796709bf4f9c11d9 Mon Sep 17 00:00:00 2001
From: johnthagen
Date: Mon, 19 Oct 2020 13:34:42 -0400
Subject: [PATCH 0035/1034] Update PyCharm integrations instructions to avoid
running on external changes (#1769)
---
docs/editor_integration.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/editor_integration.md b/docs/editor_integration.md
index 73107d6a4a1..21a6865d60e 100644
--- a/docs/editor_integration.md
+++ b/docs/editor_integration.md
@@ -72,7 +72,9 @@ On Windows / Linux / BSD:
- Output paths to refresh: `$FilePath$`
- Working directory: `$ProjectFileDir$`
- - Uncheck "Auto-save edited files to trigger the watcher" in Advanced Options
+ - In Advanced Options
+ - Uncheck "Auto-save edited files to trigger the watcher"
+ - Uncheck "Trigger the watcher on external changes"
## Wing IDE
From 407052724fa1c97ee8bcd4e96de650def00be03e Mon Sep 17 00:00:00 2001
From: Sagi Shadur
Date: Mon, 19 Oct 2020 20:35:26 +0300
Subject: [PATCH 0036/1034] Switch to pytest and tox (#1763)
* Add venv to .gitignore
* Use tox to run tests
* Make fuzz run in tox
* Split tests files
* Fix import error
---
.github/workflows/fuzz.yml | 7 +-
.github/workflows/test.yml | 5 +-
.gitignore | 1 +
test_requirements.txt | 4 +
tests/test_black.py | 230 +------------------------------------
tests/test_blackd.py | 192 +++++++++++++++++++++++++++++++
tests/util.py | 43 +++++++
tox.ini | 26 +++++
8 files changed, 275 insertions(+), 233 deletions(-)
create mode 100644 test_requirements.txt
create mode 100644 tests/test_blackd.py
create mode 100644 tests/util.py
create mode 100644 tox.ini
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 9aec3c08c63..343eed10df8 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -21,11 +21,8 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install --upgrade coverage
- python -m pip install --upgrade hypothesmith
- python -m pip install -e ".[d]"
+ python -m pip install --upgrade tox
- name: Run fuzz tests
run: |
- coverage run fuzz.py
- coverage report
+ tox -e fuzz
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e30a8b8eb68..8dd4e4f59fd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -22,9 +22,8 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install --upgrade coverage
- python -m pip install -e ".[d]"
+ python -m pip install --upgrade tox
- name: Unit tests
run: |
- coverage run -m unittest
+ tox -e py
diff --git a/.gitignore b/.gitignore
index 6b94cacd183..3207e72ae28 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ src/_black_version.py
.dmypy.json
*.swp
.hypothesis/
+venv/
\ No newline at end of file
diff --git a/test_requirements.txt b/test_requirements.txt
new file mode 100644
index 00000000000..999d05c0106
--- /dev/null
+++ b/test_requirements.txt
@@ -0,0 +1,4 @@
+pytest >= 6.0.1
+pytest-mock >= 3.2.0
+pytest-cases >= 2.1.2
+coverage >= 5.2.1
\ No newline at end of file
diff --git a/tests/test_black.py b/tests/test_black.py
index e17f43b88d4..7927b368b5d 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -22,7 +22,6 @@
Dict,
Generator,
List,
- Tuple,
Iterator,
TypeVar,
)
@@ -36,18 +35,10 @@
import black
from black import Feature, TargetVersion
-try:
- import blackd
- from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
- from aiohttp import web
-except ImportError:
- has_blackd_deps = False
-else:
- has_blackd_deps = True
-
from pathspec import PathSpec
# Import other test classes
+from tests.util import THIS_DIR, read_data, DETERMINISTIC_HEADER
from .test_primer import PrimerCLITests # noqa: F401
@@ -55,10 +46,6 @@
ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True)
fs = partial(black.format_str, mode=DEFAULT_MODE)
THIS_FILE = Path(__file__)
-THIS_DIR = THIS_FILE.parent
-PROJECT_ROOT = THIS_DIR.parent
-DETERMINISTIC_HEADER = "[Deterministic header]"
-EMPTY_LINE = "# EMPTY LINE WITH WHITESPACE" + " (this comment will be removed)"
PY36_VERSIONS = {
TargetVersion.PY36,
TargetVersion.PY37,
@@ -74,29 +61,6 @@ def dump_to_stderr(*output: str) -> str:
return "\n" + "\n".join(output) + "\n"
-def read_data(name: str, data: bool = True) -> Tuple[str, str]:
- """read_data('test_name') -> 'input', 'output'"""
- if not name.endswith((".py", ".pyi", ".out", ".diff")):
- name += ".py"
- _input: List[str] = []
- _output: List[str] = []
- base_dir = THIS_DIR / "data" if data else PROJECT_ROOT
- with open(base_dir / name, "r", encoding="utf8") as test:
- lines = test.readlines()
- result = _input
- for line in lines:
- line = line.replace(EMPTY_LINE, "")
- if line.rstrip() == "# output":
- result = _output
- continue
-
- result.append(line)
- if _input and not _output:
- # If there's no output marker, treat the entire file as already pre-formatted.
- _output = _input[:]
- return "".join(_input).strip() + "\n", "".join(_output).strip() + "\n"
-
-
@contextmanager
def cache_dir(exists: bool = True) -> Iterator[Path]:
with TemporaryDirectory() as workspace:
@@ -119,17 +83,6 @@ def event_loop() -> Iterator[None]:
loop.close()
-@contextmanager
-def skip_if_exception(e: str) -> Iterator[None]:
- try:
- yield
- except Exception as exc:
- if exc.__class__.__name__ == e:
- unittest.skip(f"Encountered expected exception {exc}, skipping")
- else:
- raise
-
-
class FakeContext(click.Context):
"""A fake click Context for when calling functions that need it."""
@@ -239,9 +192,12 @@ def test_empty_ff(self) -> None:
os.unlink(tmp_file)
self.assertFormatEqual(expected, actual)
- def test_self(self) -> None:
+ def test_run_on_test_black(self) -> None:
self.checkSourceFile("tests/test_black.py")
+ def test_run_on_test_blackd(self) -> None:
+ self.checkSourceFile("tests/test_blackd.py")
+
def test_black(self) -> None:
self.checkSourceFile("src/black/__init__.py")
@@ -1969,14 +1925,6 @@ def fail(*args: Any, **kwargs: Any) -> None:
):
ff(THIS_FILE)
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- def test_blackd_main(self) -> None:
- with patch("blackd.web.run_app"):
- result = CliRunner().invoke(blackd.main, [])
- if result.exception is not None:
- raise result.exception
- self.assertEqual(result.exit_code, 0)
-
def test_invalid_config_return_code(self) -> None:
tmp_file = Path(black.dump_to_file())
try:
@@ -2053,174 +2001,6 @@ def test_bpo_33660_workaround(self) -> None:
os.chdir(str(old_cwd))
-class BlackDTestCase(AioHTTPTestCase):
- async def get_application(self) -> web.Application:
- return blackd.make_app()
-
- # TODO: remove these decorators once the below is released
- # https://github.com/aio-libs/aiohttp/pull/3727
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_request_needs_formatting(self) -> None:
- response = await self.client.post("/", data=b"print('hello world')")
- self.assertEqual(response.status, 200)
- self.assertEqual(response.charset, "utf8")
- self.assertEqual(await response.read(), b'print("hello world")\n')
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_request_no_change(self) -> None:
- response = await self.client.post("/", data=b'print("hello world")\n')
- self.assertEqual(response.status, 204)
- self.assertEqual(await response.read(), b"")
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_request_syntax_error(self) -> None:
- response = await self.client.post("/", data=b"what even ( is")
- self.assertEqual(response.status, 400)
- content = await response.text()
- self.assertTrue(
- content.startswith("Cannot parse"),
- msg=f"Expected error to start with 'Cannot parse', got {repr(content)}",
- )
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_unsupported_version(self) -> None:
- response = await self.client.post(
- "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "2"}
- )
- self.assertEqual(response.status, 501)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_supported_version(self) -> None:
- response = await self.client.post(
- "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "1"}
- )
- self.assertEqual(response.status, 200)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_invalid_python_variant(self) -> None:
- async def check(header_value: str, expected_status: int = 400) -> None:
- response = await self.client.post(
- "/", data=b"what", headers={blackd.PYTHON_VARIANT_HEADER: header_value}
- )
- self.assertEqual(response.status, expected_status)
-
- await check("lol")
- await check("ruby3.5")
- await check("pyi3.6")
- await check("py1.5")
- await check("2.8")
- await check("py2.8")
- await check("3.0")
- await check("pypy3.0")
- await check("jython3.4")
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_pyi(self) -> None:
- source, expected = read_data("stub.pyi")
- response = await self.client.post(
- "/", data=source, headers={blackd.PYTHON_VARIANT_HEADER: "pyi"}
- )
- self.assertEqual(response.status, 200)
- self.assertEqual(await response.text(), expected)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_diff(self) -> None:
- diff_header = re.compile(
- r"(In|Out)\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d"
- )
-
- source, _ = read_data("blackd_diff.py")
- expected, _ = read_data("blackd_diff.diff")
-
- response = await self.client.post(
- "/", data=source, headers={blackd.DIFF_HEADER: "true"}
- )
- self.assertEqual(response.status, 200)
-
- actual = await response.text()
- actual = diff_header.sub(DETERMINISTIC_HEADER, actual)
- self.assertEqual(actual, expected)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_python_variant(self) -> None:
- code = (
- "def f(\n"
- " and_has_a_bunch_of,\n"
- " very_long_arguments_too,\n"
- " and_lots_of_them_as_well_lol,\n"
- " **and_very_long_keyword_arguments\n"
- "):\n"
- " pass\n"
- )
-
- async def check(header_value: str, expected_status: int) -> None:
- response = await self.client.post(
- "/", data=code, headers={blackd.PYTHON_VARIANT_HEADER: header_value}
- )
- self.assertEqual(
- response.status, expected_status, msg=await response.text()
- )
-
- await check("3.6", 200)
- await check("py3.6", 200)
- await check("3.6,3.7", 200)
- await check("3.6,py3.7", 200)
- await check("py36,py37", 200)
- await check("36", 200)
- await check("3.6.4", 200)
-
- await check("2", 204)
- await check("2.7", 204)
- await check("py2.7", 204)
- await check("3.4", 204)
- await check("py3.4", 204)
- await check("py34,py36", 204)
- await check("34", 204)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_line_length(self) -> None:
- response = await self.client.post(
- "/", data=b'print("hello")\n', headers={blackd.LINE_LENGTH_HEADER: "7"}
- )
- self.assertEqual(response.status, 200)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_invalid_line_length(self) -> None:
- response = await self.client.post(
- "/", data=b'print("hello")\n', headers={blackd.LINE_LENGTH_HEADER: "NaN"}
- )
- self.assertEqual(response.status, 400)
-
- @skip_if_exception("ClientOSError")
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @unittest_run_loop
- async def test_blackd_response_black_version_header(self) -> None:
- response = await self.client.post("/")
- self.assertIsNotNone(response.headers.get(blackd.BLACK_VERSION_HEADER))
-
-
with open(black.__file__, "r", encoding="utf-8") as _bf:
black_source_lines = _bf.readlines()
diff --git a/tests/test_blackd.py b/tests/test_blackd.py
new file mode 100644
index 00000000000..9127297c54f
--- /dev/null
+++ b/tests/test_blackd.py
@@ -0,0 +1,192 @@
+import re
+import unittest
+from unittest.mock import patch
+
+from click.testing import CliRunner
+
+from tests.util import read_data, DETERMINISTIC_HEADER, skip_if_exception
+
+try:
+ import blackd
+ from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
+ from aiohttp import web
+except ImportError:
+ has_blackd_deps = False
+else:
+ has_blackd_deps = True
+
+
+class BlackDTestCase(AioHTTPTestCase):
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ def test_blackd_main(self) -> None:
+ with patch("blackd.web.run_app"):
+ result = CliRunner().invoke(blackd.main, [])
+ if result.exception is not None:
+ raise result.exception
+ self.assertEqual(result.exit_code, 0)
+
+ async def get_application(self) -> web.Application:
+ return blackd.make_app()
+
+ # TODO: remove these decorators once the below is released
+ # https://github.com/aio-libs/aiohttp/pull/3727
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_request_needs_formatting(self) -> None:
+ response = await self.client.post("/", data=b"print('hello world')")
+ self.assertEqual(response.status, 200)
+ self.assertEqual(response.charset, "utf8")
+ self.assertEqual(await response.read(), b'print("hello world")\n')
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_request_no_change(self) -> None:
+ response = await self.client.post("/", data=b'print("hello world")\n')
+ self.assertEqual(response.status, 204)
+ self.assertEqual(await response.read(), b"")
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_request_syntax_error(self) -> None:
+ response = await self.client.post("/", data=b"what even ( is")
+ self.assertEqual(response.status, 400)
+ content = await response.text()
+ self.assertTrue(
+ content.startswith("Cannot parse"),
+ msg=f"Expected error to start with 'Cannot parse', got {repr(content)}",
+ )
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_unsupported_version(self) -> None:
+ response = await self.client.post(
+ "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "2"}
+ )
+ self.assertEqual(response.status, 501)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_supported_version(self) -> None:
+ response = await self.client.post(
+ "/", data=b"what", headers={blackd.PROTOCOL_VERSION_HEADER: "1"}
+ )
+ self.assertEqual(response.status, 200)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_invalid_python_variant(self) -> None:
+ async def check(header_value: str, expected_status: int = 400) -> None:
+ response = await self.client.post(
+ "/", data=b"what", headers={blackd.PYTHON_VARIANT_HEADER: header_value}
+ )
+ self.assertEqual(response.status, expected_status)
+
+ await check("lol")
+ await check("ruby3.5")
+ await check("pyi3.6")
+ await check("py1.5")
+ await check("2.8")
+ await check("py2.8")
+ await check("3.0")
+ await check("pypy3.0")
+ await check("jython3.4")
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_pyi(self) -> None:
+ source, expected = read_data("stub.pyi")
+ response = await self.client.post(
+ "/", data=source, headers={blackd.PYTHON_VARIANT_HEADER: "pyi"}
+ )
+ self.assertEqual(response.status, 200)
+ self.assertEqual(await response.text(), expected)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_diff(self) -> None:
+ diff_header = re.compile(
+ r"(In|Out)\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d"
+ )
+
+ source, _ = read_data("blackd_diff.py")
+ expected, _ = read_data("blackd_diff.diff")
+
+ response = await self.client.post(
+ "/", data=source, headers={blackd.DIFF_HEADER: "true"}
+ )
+ self.assertEqual(response.status, 200)
+
+ actual = await response.text()
+ actual = diff_header.sub(DETERMINISTIC_HEADER, actual)
+ self.assertEqual(actual, expected)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_python_variant(self) -> None:
+ code = (
+ "def f(\n"
+ " and_has_a_bunch_of,\n"
+ " very_long_arguments_too,\n"
+ " and_lots_of_them_as_well_lol,\n"
+ " **and_very_long_keyword_arguments\n"
+ "):\n"
+ " pass\n"
+ )
+
+ async def check(header_value: str, expected_status: int) -> None:
+ response = await self.client.post(
+ "/", data=code, headers={blackd.PYTHON_VARIANT_HEADER: header_value}
+ )
+ self.assertEqual(
+ response.status, expected_status, msg=await response.text()
+ )
+
+ await check("3.6", 200)
+ await check("py3.6", 200)
+ await check("3.6,3.7", 200)
+ await check("3.6,py3.7", 200)
+ await check("py36,py37", 200)
+ await check("36", 200)
+ await check("3.6.4", 200)
+
+ await check("2", 204)
+ await check("2.7", 204)
+ await check("py2.7", 204)
+ await check("3.4", 204)
+ await check("py3.4", 204)
+ await check("py34,py36", 204)
+ await check("34", 204)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_line_length(self) -> None:
+ response = await self.client.post(
+ "/", data=b'print("hello")\n', headers={blackd.LINE_LENGTH_HEADER: "7"}
+ )
+ self.assertEqual(response.status, 200)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_invalid_line_length(self) -> None:
+ response = await self.client.post(
+ "/", data=b'print("hello")\n', headers={blackd.LINE_LENGTH_HEADER: "NaN"}
+ )
+ self.assertEqual(response.status, 400)
+
+ @skip_if_exception("ClientOSError")
+ @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
+ @unittest_run_loop
+ async def test_blackd_response_black_version_header(self) -> None:
+ response = await self.client.post("/")
+ self.assertIsNotNone(response.headers.get(blackd.BLACK_VERSION_HEADER))
diff --git a/tests/util.py b/tests/util.py
new file mode 100644
index 00000000000..9c3d3cbc99d
--- /dev/null
+++ b/tests/util.py
@@ -0,0 +1,43 @@
+import unittest
+from contextlib import contextmanager
+from pathlib import Path
+from typing import List, Tuple, Iterator
+
+THIS_DIR = Path(__file__).parent
+PROJECT_ROOT = THIS_DIR.parent
+EMPTY_LINE = "# EMPTY LINE WITH WHITESPACE" + " (this comment will be removed)"
+DETERMINISTIC_HEADER = "[Deterministic header]"
+
+
+@contextmanager
+def skip_if_exception(e: str) -> Iterator[None]:
+ try:
+ yield
+ except Exception as exc:
+ if exc.__class__.__name__ == e:
+ unittest.skip(f"Encountered expected exception {exc}, skipping")
+ else:
+ raise
+
+
+def read_data(name: str, data: bool = True) -> Tuple[str, str]:
+ """read_data('test_name') -> 'input', 'output'"""
+ if not name.endswith((".py", ".pyi", ".out", ".diff")):
+ name += ".py"
+ _input: List[str] = []
+ _output: List[str] = []
+ base_dir = THIS_DIR / "data" if data else PROJECT_ROOT
+ with open(base_dir / name, "r", encoding="utf8") as test:
+ lines = test.readlines()
+ result = _input
+ for line in lines:
+ line = line.replace(EMPTY_LINE, "")
+ if line.rstrip() == "# output":
+ result = _output
+ continue
+
+ result.append(line)
+ if _input and not _output:
+ # If there's no output marker, treat the entire file as already pre-formatted.
+ _output = _input[:]
+ return "".join(_input).strip() + "\n", "".join(_output).strip() + "\n"
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 00000000000..500a2cad579
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,26 @@
+[tox]
+envlist = py{36,37,38,39},fuzz
+
+[testenv]
+setenv = PYTHONPATH = {toxinidir}/src
+skip_install = True
+deps =
+ -r{toxinidir}/test_requirements.txt
+commands =
+ pip install -e .[d]
+ coverage erase
+ coverage run -m pytest tests
+ coverage report
+
+[testenv:fuzz]
+skip_install = True
+deps =
+ -r{toxinidir}/test_requirements.txt
+ hypothesmith
+ lark-parser < 0.10.0
+; lark-parser's version is set due to a bug in hypothesis. Once it solved, that would be fixed.
+commands =
+ pip install -e .[d]
+ coverage erase
+ coverage run fuzz.py
+ coverage report
\ No newline at end of file
From 989ea69bd1d0a02aa6c5794d941c122f7b4958b4 Mon Sep 17 00:00:00 2001
From: Antek S <3324881+bluefish6@users.noreply.github.com>
Date: Tue, 27 Oct 2020 11:52:19 +0100
Subject: [PATCH 0037/1034] Update readme.md with current version (#1788)
* Update readme.md with current version
* Update version_control_integration.md
---
README.md | 2 +-
docs/version_control_integration.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 47472810114..d34ce146e0d 100644
--- a/README.md
+++ b/README.md
@@ -372,7 +372,7 @@ Use [pre-commit](https://pre-commit.com/). Once you
```yaml
repos:
- repo: https://github.com/psf/black
- rev: 19.10b0 # Replace by any tag/version: https://github.com/psf/black/tags
+ rev: 20.8b1 # Replace by any tag/version: https://github.com/psf/black/tags
hooks:
- id: black
language_version: python3 # Should be a command that runs python3.6+
diff --git a/docs/version_control_integration.md b/docs/version_control_integration.md
index 25dac308c47..2d8bc172eba 100644
--- a/docs/version_control_integration.md
+++ b/docs/version_control_integration.md
@@ -9,7 +9,7 @@ Use [pre-commit](https://pre-commit.com/). Once you
```yaml
repos:
- repo: https://github.com/psf/black
- rev: 19.10b0 # Replace by any tag/version: https://github.com/psf/black/tags
+ rev: 20.8b1 # Replace by any tag/version: https://github.com/psf/black/tags
hooks:
- id: black
language_version: python3 # Should be a command that runs python3.6+
From cabeb5b5457b8fd29d608eca944be6074bd3f31f Mon Sep 17 00:00:00 2001
From: Bibo-Joshi
Date: Tue, 27 Oct 2020 21:59:43 +0100
Subject: [PATCH 0038/1034] Document some culprits with pre-commit (#1783)
* Document some culprits with pre-commit
* make pre-commit happy
* don't use monospace for black & pre-commit
Co-authored-by: Hugo van Kemenade
* make pre-commit happy again
Co-authored-by: Hugo van Kemenade
---
docs/version_control_integration.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docs/version_control_integration.md b/docs/version_control_integration.md
index 2d8bc172eba..0e09854a2e5 100644
--- a/docs/version_control_integration.md
+++ b/docs/version_control_integration.md
@@ -23,6 +23,11 @@ for your project. See _Black_'s own
[pyproject.toml](https://github.com/psf/black/blob/master/pyproject.toml) for an
example.
+When using the `--diff` flag with `pre-commit`, you must also use the `--check` flag.
+When you want to run _Black_ only on specific files in pre-commit, either use
+pre-commit's own `files` and `exclude` or, when using _Black_'s `--include`, set
+`--force-exclude` to the negated regex of `--include`.
+
If you're already using Python 3.7, switch the `language_version` accordingly. Finally,
`stable` is a branch that tracks the latest release on PyPI. If you'd rather run on
master, this is also an option.
From e6cd10e7615f4df537e2eaefcf3904a4feecad1f Mon Sep 17 00:00:00 2001
From: Sagi Shadur
Date: Fri, 30 Oct 2020 17:12:04 +0200
Subject: [PATCH 0039/1034] Extract formatting tests (#1785)
* Update test versions
* Use parametrize to remove tests duplications
* Extract sources format tests
* Fix mypy errors
* Fix .travis.yml
---
.travis.yml | 4 +-
test_requirements.txt | 9 +-
tests/test_black.py | 416 ++----------------------------------------
tests/test_format.py | 98 ++++++++++
tests/util.py | 48 ++++-
5 files changed, 160 insertions(+), 415 deletions(-)
create mode 100644 tests/test_format.py
diff --git a/.travis.yml b/.travis.yml
index 86cf24df51b..f035343c6fb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,9 +4,9 @@ cache:
directories:
- $HOME/.cache/pre-commit
env:
- - TEST_CMD="coverage run -m unittest"
+ - TEST_CMD="tox -e py"
install:
- - pip install coverage coveralls pre-commit
+ - pip install coverage coveralls pre-commit tox
- pip install -e '.[d]'
script:
- $TEST_CMD
diff --git a/test_requirements.txt b/test_requirements.txt
index 999d05c0106..3e65cdb669f 100644
--- a/test_requirements.txt
+++ b/test_requirements.txt
@@ -1,4 +1,5 @@
-pytest >= 6.0.1
-pytest-mock >= 3.2.0
-pytest-cases >= 2.1.2
-coverage >= 5.2.1
\ No newline at end of file
+pytest >= 6.1.1
+pytest-mock >= 3.3.1
+pytest-cases >= 2.3.0
+coverage >= 5.3
+parameterized >= 0.7.4
\ No newline at end of file
diff --git a/tests/test_black.py b/tests/test_black.py
index 7927b368b5d..b0cf6ed5caa 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -5,7 +5,6 @@
from concurrent.futures import ThreadPoolExecutor
from contextlib import contextmanager
from dataclasses import replace
-from functools import partial
import inspect
from io import BytesIO, TextIOWrapper
import os
@@ -38,13 +37,19 @@
from pathspec import PathSpec
# Import other test classes
-from tests.util import THIS_DIR, read_data, DETERMINISTIC_HEADER
+from tests.util import (
+ THIS_DIR,
+ read_data,
+ DETERMINISTIC_HEADER,
+ BlackBaseTestCase,
+ DEFAULT_MODE,
+ fs,
+ ff,
+ dump_to_stderr,
+)
from .test_primer import PrimerCLITests # noqa: F401
-DEFAULT_MODE = black.FileMode(experimental_string_processing=True)
-ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True)
-fs = partial(black.format_str, mode=DEFAULT_MODE)
THIS_FILE = Path(__file__)
PY36_VERSIONS = {
TargetVersion.PY36,
@@ -57,10 +62,6 @@
R = TypeVar("R")
-def dump_to_stderr(*output: str) -> str:
- return "\n" + "\n".join(output) + "\n"
-
-
@contextmanager
def cache_dir(exists: bool = True) -> Iterator[Path]:
with TemporaryDirectory() as workspace:
@@ -122,29 +123,7 @@ def isolation(self, *args: Any, **kwargs: Any) -> Generator[BinaryIO, None, None
sys.stderr = hold_stderr
-class BlackTestCase(unittest.TestCase):
- maxDiff = None
- _diffThreshold = 2 ** 20
-
- def assertFormatEqual(self, expected: str, actual: str) -> None:
- if actual != expected and not os.environ.get("SKIP_AST_PRINT"):
- bdv: black.DebugVisitor[Any]
- black.out("Expected tree:", fg="green")
- try:
- exp_node = black.lib2to3_parse(expected)
- bdv = black.DebugVisitor()
- list(bdv.visit(exp_node))
- except Exception as ve:
- black.err(str(ve))
- black.out("Actual tree:", fg="red")
- try:
- exp_node = black.lib2to3_parse(actual)
- bdv = black.DebugVisitor()
- list(bdv.visit(exp_node))
- except Exception as ve:
- black.err(str(ve))
- self.assertMultiLineEqual(expected, actual)
-
+class BlackTestCase(BlackBaseTestCase):
def invokeBlack(
self, args: List[str], exit_code: int = 0, ignore_config: bool = True
) -> None:
@@ -163,16 +142,6 @@ def invokeBlack(
),
)
- @patch("black.dump_to_file", dump_to_stderr)
- def checkSourceFile(self, name: str, mode: black.FileMode = DEFAULT_MODE) -> None:
- path = THIS_DIR.parent / name
- source, expected = read_data(str(path), data=False)
- actual = fs(source, mode=mode)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, mode)
- self.assertFalse(ff(path))
-
@patch("black.dump_to_file", dump_to_stderr)
def test_empty(self) -> None:
source = expected = ""
@@ -192,48 +161,6 @@ def test_empty_ff(self) -> None:
os.unlink(tmp_file)
self.assertFormatEqual(expected, actual)
- def test_run_on_test_black(self) -> None:
- self.checkSourceFile("tests/test_black.py")
-
- def test_run_on_test_blackd(self) -> None:
- self.checkSourceFile("tests/test_blackd.py")
-
- def test_black(self) -> None:
- self.checkSourceFile("src/black/__init__.py")
-
- def test_pygram(self) -> None:
- self.checkSourceFile("src/blib2to3/pygram.py")
-
- def test_pytree(self) -> None:
- self.checkSourceFile("src/blib2to3/pytree.py")
-
- def test_conv(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/conv.py")
-
- def test_driver(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/driver.py")
-
- def test_grammar(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/grammar.py")
-
- def test_literals(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/literals.py")
-
- def test_parse(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/parse.py")
-
- def test_pgen(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/pgen.py")
-
- def test_tokenize(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/tokenize.py")
-
- def test_token(self) -> None:
- self.checkSourceFile("src/blib2to3/pgen2/token.py")
-
- def test_setup(self) -> None:
- self.checkSourceFile("setup.py")
-
def test_piping(self) -> None:
source, expected = read_data("src/black/__init__", data=False)
result = BlackRunner().invoke(
@@ -291,22 +218,6 @@ def test_piping_diff_with_color(self) -> None:
self.assertIn("\033[31m", actual)
self.assertIn("\033[0m", actual)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_function(self) -> None:
- source, expected = read_data("function")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_function2(self) -> None:
- source, expected = read_data("function2")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def _test_wip(self) -> None:
source, expected = read_data("wip")
@@ -322,14 +233,6 @@ def _test_wip(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, black.FileMode())
- @patch("black.dump_to_file", dump_to_stderr)
- def test_function_trailing_comma(self) -> None:
- source, expected = read_data("function_trailing_comma")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@unittest.expectedFailure
@patch("black.dump_to_file", dump_to_stderr)
def test_trailing_comma_optional_parens_stability1(self) -> None:
@@ -351,14 +254,6 @@ def test_trailing_comma_optional_parens_stability3(self) -> None:
actual = fs(source)
black.assert_stable(source, actual, DEFAULT_MODE)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_expression(self) -> None:
- source, expected = read_data("expression")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_pep_572(self) -> None:
source, expected = read_data("pep_572")
@@ -434,14 +329,6 @@ def test_expression_diff_with_color(self) -> None:
self.assertIn("\033[31m", actual)
self.assertIn("\033[0m", actual)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_fstring(self) -> None:
- source, expected = read_data("fstring")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_pep_570(self) -> None:
source, expected = read_data("pep_570")
@@ -472,14 +359,6 @@ def test_string_quotes(self) -> None:
black.assert_equivalent(source, not_normalized)
black.assert_stable(source, not_normalized, mode=mode)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_docstring(self) -> None:
- source, expected = read_data("docstring")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_docstring_no_string_normalization(self) -> None:
"""Like test_docstring but with string normalization off."""
@@ -490,14 +369,6 @@ def test_docstring_no_string_normalization(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, mode)
- def test_long_strings(self) -> None:
- """Tests for splitting long strings."""
- source, expected = read_data("long_strings")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
def test_long_strings_flag_disabled(self) -> None:
"""Tests for turning off the string processing logic."""
source, expected = read_data("long_strings_flag_disabled")
@@ -506,162 +377,6 @@ def test_long_strings_flag_disabled(self) -> None:
self.assertFormatEqual(expected, actual)
black.assert_stable(expected, actual, mode)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_long_strings__edge_case(self) -> None:
- """Edge-case tests for splitting long strings."""
- source, expected = read_data("long_strings__edge_case")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_long_strings__regression(self) -> None:
- """Regression tests for splitting long strings."""
- source, expected = read_data("long_strings__regression")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_slices(self) -> None:
- source, expected = read_data("slices")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_percent_precedence(self) -> None:
- source, expected = read_data("percent_precedence")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments(self) -> None:
- source, expected = read_data("comments")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments2(self) -> None:
- source, expected = read_data("comments2")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments3(self) -> None:
- source, expected = read_data("comments3")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments4(self) -> None:
- source, expected = read_data("comments4")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments5(self) -> None:
- source, expected = read_data("comments5")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments6(self) -> None:
- source, expected = read_data("comments6")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comments7(self) -> None:
- source, expected = read_data("comments7")
- mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY38})
- actual = fs(source, mode=mode)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_comment_after_escaped_newline(self) -> None:
- source, expected = read_data("comment_after_escaped_newline")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_cantfit(self) -> None:
- source, expected = read_data("cantfit")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_import_spacing(self) -> None:
- source, expected = read_data("import_spacing")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_composition(self) -> None:
- source, expected = read_data("composition")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_composition_no_trailing_comma(self) -> None:
- source, expected = read_data("composition_no_trailing_comma")
- mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY38})
- actual = fs(source, mode=mode)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_empty_lines(self) -> None:
- source, expected = read_data("empty_lines")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_remove_parens(self) -> None:
- source, expected = read_data("remove_parens")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_string_prefixes(self) -> None:
- source, expected = read_data("string_prefixes")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_numeric_literals(self) -> None:
source, expected = read_data("numeric_literals")
@@ -680,21 +395,6 @@ def test_numeric_literals_ignoring_underscores(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, mode)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_numeric_literals_py2(self) -> None:
- source, expected = read_data("numeric_literals_py2")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_python2(self) -> None:
- source, expected = read_data("python2")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_python2_print_function(self) -> None:
source, expected = read_data("python2_print_function")
@@ -704,14 +404,6 @@ def test_python2_print_function(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, mode)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_python2_unicode_literals(self) -> None:
- source, expected = read_data("python2_unicode_literals")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
@patch("black.dump_to_file", dump_to_stderr)
def test_stub(self) -> None:
mode = replace(DEFAULT_MODE, is_pyi=True)
@@ -770,78 +462,6 @@ def test_python39(self) -> None:
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, DEFAULT_MODE)
- @patch("black.dump_to_file", dump_to_stderr)
- def test_fmtonoff(self) -> None:
- source, expected = read_data("fmtonoff")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_fmtonoff2(self) -> None:
- source, expected = read_data("fmtonoff2")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_fmtonoff3(self) -> None:
- source, expected = read_data("fmtonoff3")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_fmtonoff4(self) -> None:
- source, expected = read_data("fmtonoff4")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_remove_empty_parentheses_after_class(self) -> None:
- source, expected = read_data("class_blank_parentheses")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_new_line_between_class_and_code(self) -> None:
- source, expected = read_data("class_methods_new_line")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_bracket_match(self) -> None:
- source, expected = read_data("bracketmatch")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_tuple_assign(self) -> None:
- source, expected = read_data("tupleassign")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
- @patch("black.dump_to_file", dump_to_stderr)
- def test_beginning_backslash(self) -> None:
- source, expected = read_data("beginning_backslash")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
def test_tab_comment_indentation(self) -> None:
contents_tab = "if 1:\n\tif 2:\n\t\tpass\n\t# comment\n\tpass\n"
contents_spc = "if 1:\n if 2:\n pass\n # comment\n pass\n"
@@ -1569,13 +1189,6 @@ def test_read_cache_line_lengths(self) -> None:
two = black.read_cache(short_mode)
self.assertNotIn(path, two)
- def test_tricky_unicode_symbols(self) -> None:
- source, expected = read_data("tricky_unicode_symbols")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
def test_single_file_force_pyi(self) -> None:
pyi_mode = replace(DEFAULT_MODE, is_pyi=True)
contents, expected = read_data("force_pyi")
@@ -1672,13 +1285,6 @@ def test_multi_file_force_py36(self) -> None:
self.assertIn(path, pyi_cache)
self.assertNotIn(path, normal_cache)
- def test_collections(self) -> None:
- source, expected = read_data("collections")
- actual = fs(source)
- self.assertFormatEqual(expected, actual)
- black.assert_equivalent(source, actual)
- black.assert_stable(source, actual, DEFAULT_MODE)
-
def test_pipe_force_py36(self) -> None:
source, expected = read_data("force_py36")
result = CliRunner().invoke(
diff --git a/tests/test_format.py b/tests/test_format.py
new file mode 100644
index 00000000000..e4677707e3c
--- /dev/null
+++ b/tests/test_format.py
@@ -0,0 +1,98 @@
+from unittest.mock import patch
+
+import black
+from parameterized import parameterized
+
+from tests.util import (
+ BlackBaseTestCase,
+ fs,
+ ff,
+ DEFAULT_MODE,
+ dump_to_stderr,
+ read_data,
+ THIS_DIR,
+)
+
+SIMPLE_CASES = [
+ "beginning_backslash",
+ "bracketmatch",
+ "cantfit",
+ "class_blank_parentheses",
+ "class_methods_new_line",
+ "collections",
+ "comments",
+ "comments2",
+ "comments3",
+ "comments4",
+ "comments5",
+ "comments6",
+ "comments7",
+ "comment_after_escaped_newline",
+ "composition",
+ "composition_no_trailing_comma",
+ "docstring",
+ "empty_lines",
+ "expression",
+ "fmtonoff",
+ "fmtonoff2",
+ "fmtonoff3",
+ "fmtonoff4",
+ "fstring",
+ "function",
+ "function2",
+ "function_trailing_comma",
+ "import_spacing",
+ "long_strings",
+ "long_strings__edge_case",
+ "long_strings__regression",
+ "numeric_literals_py2",
+ "percent_precedence",
+ "python2",
+ "python2_unicode_literals",
+ "remove_parens",
+ "slices",
+ "string_prefixes",
+ "tricky_unicode_symbols",
+ "tupleassign",
+]
+
+
+SOURCES = [
+ "tests/test_black.py",
+ "tests/test_format.py",
+ "tests/test_blackd.py",
+ "src/black/__init__.py",
+ "src/blib2to3/pygram.py",
+ "src/blib2to3/pytree.py",
+ "src/blib2to3/pgen2/conv.py",
+ "src/blib2to3/pgen2/driver.py",
+ "src/blib2to3/pgen2/grammar.py",
+ "src/blib2to3/pgen2/literals.py",
+ "src/blib2to3/pgen2/parse.py",
+ "src/blib2to3/pgen2/pgen.py",
+ "src/blib2to3/pgen2/tokenize.py",
+ "src/blib2to3/pgen2/token.py",
+ "setup.py",
+]
+
+
+class TestSimpleFormat(BlackBaseTestCase):
+ @parameterized.expand(SIMPLE_CASES)
+ @patch("black.dump_to_file", dump_to_stderr)
+ def test_simple_format(self, filename: str) -> None:
+ source, expected = read_data(filename)
+ actual = fs(source)
+ self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(source, actual)
+ black.assert_stable(source, actual, DEFAULT_MODE)
+
+ @parameterized.expand(SOURCES)
+ @patch("black.dump_to_file", dump_to_stderr)
+ def test_source_is_formatted(self, filename: str) -> None:
+ path = THIS_DIR.parent / filename
+ source, expected = read_data(str(path), data=False)
+ actual = fs(source, mode=DEFAULT_MODE)
+ self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(source, actual)
+ black.assert_stable(source, actual, DEFAULT_MODE)
+ self.assertFalse(ff(path))
diff --git a/tests/util.py b/tests/util.py
index 9c3d3cbc99d..da65ed0cc93 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -1,7 +1,10 @@
+import os
import unittest
from contextlib import contextmanager
from pathlib import Path
-from typing import List, Tuple, Iterator
+from typing import List, Tuple, Iterator, Any
+import black
+from functools import partial
THIS_DIR = Path(__file__).parent
PROJECT_ROOT = THIS_DIR.parent
@@ -9,6 +12,39 @@
DETERMINISTIC_HEADER = "[Deterministic header]"
+DEFAULT_MODE = black.FileMode(experimental_string_processing=True)
+ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True)
+fs = partial(black.format_str, mode=DEFAULT_MODE)
+
+
+def dump_to_stderr(*output: str) -> str:
+ return "\n" + "\n".join(output) + "\n"
+
+
+class BlackBaseTestCase(unittest.TestCase):
+ maxDiff = None
+ _diffThreshold = 2 ** 20
+
+ def assertFormatEqual(self, expected: str, actual: str) -> None:
+ if actual != expected and not os.environ.get("SKIP_AST_PRINT"):
+ bdv: black.DebugVisitor[Any]
+ black.out("Expected tree:", fg="green")
+ try:
+ exp_node = black.lib2to3_parse(expected)
+ bdv = black.DebugVisitor()
+ list(bdv.visit(exp_node))
+ except Exception as ve:
+ black.err(str(ve))
+ black.out("Actual tree:", fg="red")
+ try:
+ exp_node = black.lib2to3_parse(actual)
+ bdv = black.DebugVisitor()
+ list(bdv.visit(exp_node))
+ except Exception as ve:
+ black.err(str(ve))
+ self.assertMultiLineEqual(expected, actual)
+
+
@contextmanager
def skip_if_exception(e: str) -> Iterator[None]:
try:
@@ -24,11 +60,15 @@ def read_data(name: str, data: bool = True) -> Tuple[str, str]:
"""read_data('test_name') -> 'input', 'output'"""
if not name.endswith((".py", ".pyi", ".out", ".diff")):
name += ".py"
- _input: List[str] = []
- _output: List[str] = []
base_dir = THIS_DIR / "data" if data else PROJECT_ROOT
- with open(base_dir / name, "r", encoding="utf8") as test:
+ return read_data_from_file(base_dir / name)
+
+
+def read_data_from_file(file_name: Path) -> Tuple[str, str]:
+ with open(file_name, "r", encoding="utf8") as test:
lines = test.readlines()
+ _input: List[str] = []
+ _output: List[str] = []
result = _input
for line in lines:
line = line.replace(EMPTY_LINE, "")
From b64fd2bbec420ff71f7592f40816ae7de2fa4a15 Mon Sep 17 00:00:00 2001
From: Shota Ray Imaki
Date: Sat, 31 Oct 2020 00:13:55 +0900
Subject: [PATCH 0040/1034] Add compatible configuration files. (psf#1789)
(#1792)
* Add compatible configuration files. (psf#1789)
* Simplify isort configuration files. (#1789)
---
docs/compatible_configs.md | 3 +++
docs/compatible_configs/flake8/.flake8 | 3 +++
docs/compatible_configs/flake8/setup.cfg | 3 +++
docs/compatible_configs/flake8/tox.ini | 3 +++
docs/compatible_configs/isort/.editorconfig | 2 ++
docs/compatible_configs/isort/.isort.cfg | 2 ++
docs/compatible_configs/isort/pyproject.toml | 2 ++
docs/compatible_configs/isort/setup.cfg | 2 ++
docs/compatible_configs/pylint/pylintrc | 5 +++++
docs/compatible_configs/pylint/pyproject.toml | 5 +++++
docs/compatible_configs/pylint/setup.cfg | 5 +++++
11 files changed, 35 insertions(+)
create mode 100644 docs/compatible_configs/flake8/.flake8
create mode 100644 docs/compatible_configs/flake8/setup.cfg
create mode 100644 docs/compatible_configs/flake8/tox.ini
create mode 100644 docs/compatible_configs/isort/.editorconfig
create mode 100644 docs/compatible_configs/isort/.isort.cfg
create mode 100644 docs/compatible_configs/isort/pyproject.toml
create mode 100644 docs/compatible_configs/isort/setup.cfg
create mode 100644 docs/compatible_configs/pylint/pylintrc
create mode 100644 docs/compatible_configs/pylint/pyproject.toml
create mode 100644 docs/compatible_configs/pylint/setup.cfg
diff --git a/docs/compatible_configs.md b/docs/compatible_configs.md
index 990820a6771..c6724e77e57 100644
--- a/docs/compatible_configs.md
+++ b/docs/compatible_configs.md
@@ -10,6 +10,9 @@ tools out there.
(e.g. `pyproject.toml`). The provided examples are to only configure their corresponding
tools, using **their** supported file formats.
+Compatible configuration files can be
+[found here](https://github.com/psf/black/blob/master/docs/compatible_configs/).
+
## isort
[isort](https://pypi.org/p/isort/) helps to sort and format imports in your Python code.
diff --git a/docs/compatible_configs/flake8/.flake8 b/docs/compatible_configs/flake8/.flake8
new file mode 100644
index 00000000000..8dd399ab55b
--- /dev/null
+++ b/docs/compatible_configs/flake8/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 88
+extend-ignore = E203
diff --git a/docs/compatible_configs/flake8/setup.cfg b/docs/compatible_configs/flake8/setup.cfg
new file mode 100644
index 00000000000..8dd399ab55b
--- /dev/null
+++ b/docs/compatible_configs/flake8/setup.cfg
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 88
+extend-ignore = E203
diff --git a/docs/compatible_configs/flake8/tox.ini b/docs/compatible_configs/flake8/tox.ini
new file mode 100644
index 00000000000..8dd399ab55b
--- /dev/null
+++ b/docs/compatible_configs/flake8/tox.ini
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 88
+extend-ignore = E203
diff --git a/docs/compatible_configs/isort/.editorconfig b/docs/compatible_configs/isort/.editorconfig
new file mode 100644
index 00000000000..edc849a54a6
--- /dev/null
+++ b/docs/compatible_configs/isort/.editorconfig
@@ -0,0 +1,2 @@
+[*.py]
+profile = black
diff --git a/docs/compatible_configs/isort/.isort.cfg b/docs/compatible_configs/isort/.isort.cfg
new file mode 100644
index 00000000000..f238bf7ea13
--- /dev/null
+++ b/docs/compatible_configs/isort/.isort.cfg
@@ -0,0 +1,2 @@
+[settings]
+profile = black
diff --git a/docs/compatible_configs/isort/pyproject.toml b/docs/compatible_configs/isort/pyproject.toml
new file mode 100644
index 00000000000..cea9915bebf
--- /dev/null
+++ b/docs/compatible_configs/isort/pyproject.toml
@@ -0,0 +1,2 @@
+[tool.isort]
+profile = black
diff --git a/docs/compatible_configs/isort/setup.cfg b/docs/compatible_configs/isort/setup.cfg
new file mode 100644
index 00000000000..c76db01ff4e
--- /dev/null
+++ b/docs/compatible_configs/isort/setup.cfg
@@ -0,0 +1,2 @@
+[isort]
+profile = black
diff --git a/docs/compatible_configs/pylint/pylintrc b/docs/compatible_configs/pylint/pylintrc
new file mode 100644
index 00000000000..7abddd2c330
--- /dev/null
+++ b/docs/compatible_configs/pylint/pylintrc
@@ -0,0 +1,5 @@
+[MESSAGES CONTROL]
+disable = C0330, C0326
+
+[format]
+max-line-length = 88
diff --git a/docs/compatible_configs/pylint/pyproject.toml b/docs/compatible_configs/pylint/pyproject.toml
new file mode 100644
index 00000000000..49ad7a2c771
--- /dev/null
+++ b/docs/compatible_configs/pylint/pyproject.toml
@@ -0,0 +1,5 @@
+[tool.pylint.messages_control]
+disable = "C0330, C0326"
+
+[tool.pylint.format]
+max-line-length = "88"
diff --git a/docs/compatible_configs/pylint/setup.cfg b/docs/compatible_configs/pylint/setup.cfg
new file mode 100644
index 00000000000..3ada24530ea
--- /dev/null
+++ b/docs/compatible_configs/pylint/setup.cfg
@@ -0,0 +1,5 @@
+[pylint]
+max-line-length = 88
+
+[pylint.messages_control]
+disable = C0330, C0326
From 5d978df8b54d4fb102142508353a04932a4b5b04 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 30 Oct 2020 08:15:09 -0700
Subject: [PATCH 0041/1034] Bump cryptography from 3.1 to 3.2 (#1791)
Bumps [cryptography](https://github.com/pyca/cryptography) from 3.1 to 3.2.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/3.1...3.2)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Pipfile.lock | 355 +++++++++++++++++++++++++--------------------------
1 file changed, 172 insertions(+), 183 deletions(-)
diff --git a/Pipfile.lock b/Pipfile.lock
index e09d69ea83d..95b7613114a 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -53,7 +53,6 @@
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
],
- "markers": "python_full_version >= '3.5.3'",
"version": "==3.0.1"
},
"attrs": {
@@ -61,7 +60,6 @@
"sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
"sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.2.0"
},
"black": {
@@ -92,16 +90,13 @@
"sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84"
],
"index": "pypi",
- "python_version <": "3.7",
- "version": "==0.6",
- "version >": "0.6"
+ "version": "==0.6"
},
"idna": {
"hashes": [
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.10"
},
"multidict": {
@@ -124,7 +119,6 @@
"sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
"sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
],
- "markers": "python_version >= '3.5'",
"version": "==4.7.6"
},
"mypy-extensions": {
@@ -170,26 +164,10 @@
"index": "pypi",
"version": "==2020.7.14"
},
- "setuptools-scm": {
- "hashes": [
- "sha256:09c659d1d6680811c43f476a33c6d3d9872416580786e96bd29ea03e6a818e41",
- "sha256:69258e2eeba5f7ce1ed7a5f109519580fa3578250f8e4d6684859f86d1b15826",
- "sha256:731550a27e3901ee501c3bf99140b5436b8eeba341a9d19911cf364b8d573293",
- "sha256:892e63b4983f9e30f9e8bf89ad03d2a02a47e6e5ced09b03ae6fe952ade8a579",
- "sha256:a8994582e716ec690f33fec70cca0f85bd23ec974e3f783233e4879090a7faa8",
- "sha256:b42c150c34d6120babf3646abd7513e032be2e230b3d2034f27404c65aa0c977",
- "sha256:eaaec16b7af25c5f532b5af2332213bb6223d15cca4518f6dbc4c055641c86fd",
- "sha256:efc928d6a64162c88cdc85fa4b84adfbd6dbf9f9b04319bc495eb16dcfaae00a"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==4.1.2"
- },
"toml": {
"hashes": [
- "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88",
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
"index": "pypi",
"version": "==0.10.1"
@@ -198,9 +176,11 @@
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
@@ -209,12 +189,16 @@
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
+ "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
@@ -232,26 +216,41 @@
},
"yarl": {
"hashes": [
- "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409",
- "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593",
- "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2",
- "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8",
- "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d",
- "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692",
- "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02",
- "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a",
- "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8",
- "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6",
- "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511",
- "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e",
- "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a",
- "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb",
- "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f",
- "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317",
- "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"
- ],
- "markers": "python_version >= '3.5'",
- "version": "==1.5.1"
+ "sha256:03b7a44384ad60be1b7be93c2a24dc74895f8d767ea0bce15b2f6fc7695a3843",
+ "sha256:076157404db9db4bb3fa9db22db319bbb36d075eeab19ba018ce20ae0cacf037",
+ "sha256:1c05ae3d5ea4287470046a2c2754f0a4c171b84ea72c8a691f776eb1753dfb91",
+ "sha256:2467baf8233f7c64048df37e11879c553943ffe7f373e689711ec2807ea13805",
+ "sha256:2bb2e21cf062dfbe985c3cd4618bae9f25271efcad9e7be1277861247eee9839",
+ "sha256:311effab3b3828ab34f0e661bb57ff422f67d5c33056298bda4c12195251f8dd",
+ "sha256:3526cb5905907f0e42bee7ef57ae4a5f02bc27dcac27859269e2bba0caa4c2b6",
+ "sha256:39b1e586f34b1d2512c9b39aa3cf24c870c972d525e36edc9ee19065db4737bb",
+ "sha256:4bed5cd7c8e69551eb19df15295ba90e62b9a6a1149c76eb4a9bab194402a156",
+ "sha256:51c6d3cf7a1f1fbe134bb92f33b7affd94d6de24cd64b466eb12de52120fb8c6",
+ "sha256:59f78b5da34ddcffb663b772f7619e296518712e022e57fc5d9f921818e2ab7c",
+ "sha256:6f29115b0c330da25a04f48612d75333bca04521181a666ca0b8761005a99150",
+ "sha256:73d4e1e1ef5e52d526c92f07d16329e1678612c6a81dd8101fdcae11a72de15c",
+ "sha256:9b48d31f8d881713fd461abfe7acbb4dcfeb47cec3056aa83f2fbcd2244577f7",
+ "sha256:a1fd575dd058e10ad4c35065e7c3007cc74d142f622b14e168d8a273a2fa8713",
+ "sha256:b3dd1052afd436ba737e61f5d3bed1f43a7f9a33fc58fbe4226eb919a7006019",
+ "sha256:b99c25ed5c355b35d1e6dae87ac7297a4844a57dc5766b173b88b6163a36eb0d",
+ "sha256:c056e86bff5a0b566e0d9fab4f67e83b12ae9cbcd250d334cbe2005bbe8c96f2",
+ "sha256:c45b49b59a5724869899798e1bbd447ac486215269511d3b76b4c235a1b766b6",
+ "sha256:cd623170c729a865037828e3f99f8ebdb22a467177a539680dfc5670b74c84e2",
+ "sha256:d25d3311794e6c71b608d7c47651c8f65eea5ab15358a27f29330b3475e8f8e5",
+ "sha256:d695439c201ed340745250f9eb4dfe8d32bf1e680c16477107b8f3ce4bff4fdb",
+ "sha256:d77f6c9133d2aabb290a7846aaa74ec14d7b5ab35b01591fac5a70c4a8c959a2",
+ "sha256:d894a2442d2cd20a3b0b0dce5a353d316c57d25a2b445e03f7eac90eee27b8af",
+ "sha256:db643ce2b58a4bd11a82348225c53c76ecdd82bb37cf4c085e6df1b676f4038c",
+ "sha256:e3a0c43a26dfed955b2a06fdc4d51d2c51bc2200aff8ce8faf14e676ea8c8862",
+ "sha256:e77bf79ad1ccae672eab22453838382fe9029fc27c8029e84913855512a587d8",
+ "sha256:f2f0174cb15435957d3b751093f89aede77df59a499ab7516bbb633b77ead13a",
+ "sha256:f3031c78edf10315abe232254e6a36b65afe65fded41ee54ed7976d0b2cdf0da",
+ "sha256:f4c007156732866aa4507d619fe6f8f2748caabed4f66b276ccd97c82572620c",
+ "sha256:f4f27ff3dd80bc7c402def211a47291ea123d59a23f59fe18fc0e81e3e71f385",
+ "sha256:f57744fc61e118b5d114ae8077d8eb9df4d2d2c11e2af194e21f0c11ed9dcf6c",
+ "sha256:f835015a825980b65356e9520979a1564c56efea7da7d4b68a14d4a07a3a7336"
+ ],
+ "version": "==1.6.2"
}
},
"develop": {
@@ -301,7 +300,6 @@
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
],
- "markers": "python_full_version >= '3.5.3'",
"version": "==3.0.1"
},
"attrs": {
@@ -309,7 +307,6 @@
"sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
"sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.2.0"
},
"babel": {
@@ -317,7 +314,6 @@
"sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
"sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.8.0"
},
"black": {
@@ -332,7 +328,6 @@
"sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080",
"sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==3.2.1"
},
"certifi": {
@@ -344,43 +339,50 @@
},
"cffi": {
"hashes": [
- "sha256:0da50dcbccd7cb7e6c741ab7912b2eff48e85af217d72b57f80ebc616257125e",
- "sha256:12a453e03124069b6896107ee133ae3ab04c624bb10683e1ed1c1663df17c13c",
- "sha256:15419020b0e812b40d96ec9d369b2bc8109cc3295eac6e013d3261343580cc7e",
- "sha256:15a5f59a4808f82d8ec7364cbace851df591c2d43bc76bcbe5c4543a7ddd1bf1",
- "sha256:23e44937d7695c27c66a54d793dd4b45889a81b35c0751ba91040fe825ec59c4",
- "sha256:29c4688ace466a365b85a51dcc5e3c853c1d283f293dfcc12f7a77e498f160d2",
- "sha256:57214fa5430399dffd54f4be37b56fe22cedb2b98862550d43cc085fb698dc2c",
- "sha256:577791f948d34d569acb2d1add5831731c59d5a0c50a6d9f629ae1cefd9ca4a0",
- "sha256:6539314d84c4d36f28d73adc1b45e9f4ee2a89cdc7e5d2b0a6dbacba31906798",
- "sha256:65867d63f0fd1b500fa343d7798fa64e9e681b594e0a07dc934c13e76ee28fb1",
- "sha256:672b539db20fef6b03d6f7a14b5825d57c98e4026401fce838849f8de73fe4d4",
- "sha256:6843db0343e12e3f52cc58430ad559d850a53684f5b352540ca3f1bc56df0731",
- "sha256:7057613efefd36cacabbdbcef010e0a9c20a88fc07eb3e616019ea1692fa5df4",
- "sha256:76ada88d62eb24de7051c5157a1a78fd853cca9b91c0713c2e973e4196271d0c",
- "sha256:837398c2ec00228679513802e3744d1e8e3cb1204aa6ad408b6aff081e99a487",
- "sha256:8662aabfeab00cea149a3d1c2999b0731e70c6b5bac596d95d13f643e76d3d4e",
- "sha256:95e9094162fa712f18b4f60896e34b621df99147c2cee216cfa8f022294e8e9f",
- "sha256:99cc66b33c418cd579c0f03b77b94263c305c389cb0c6972dac420f24b3bf123",
- "sha256:9b219511d8b64d3fa14261963933be34028ea0e57455baf6781fe399c2c3206c",
- "sha256:ae8f34d50af2c2154035984b8b5fc5d9ed63f32fe615646ab435b05b132ca91b",
- "sha256:b9aa9d8818c2e917fa2c105ad538e222a5bce59777133840b93134022a7ce650",
- "sha256:bf44a9a0141a082e89c90e8d785b212a872db793a0080c20f6ae6e2a0ebf82ad",
- "sha256:c0b48b98d79cf795b0916c57bebbc6d16bb43b9fc9b8c9f57f4cf05881904c75",
- "sha256:da9d3c506f43e220336433dffe643fbfa40096d408cb9b7f2477892f369d5f82",
- "sha256:e4082d832e36e7f9b2278bc774886ca8207346b99f278e54c9de4834f17232f7",
- "sha256:e4b9b7af398c32e408c00eb4e0d33ced2f9121fd9fb978e6c1b57edd014a7d15",
- "sha256:e613514a82539fc48291d01933951a13ae93b6b444a88782480be32245ed4afa",
- "sha256:f5033952def24172e60493b68717792e3aebb387a8d186c43c020d9363ee7281"
- ],
- "version": "==1.14.2"
+ "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d",
+ "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b",
+ "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4",
+ "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f",
+ "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3",
+ "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579",
+ "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537",
+ "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e",
+ "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05",
+ "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171",
+ "sha256:33c6cdc071ba5cd6d96769c8969a0531be2d08c2628a0143a10a7dcffa9719ca",
+ "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522",
+ "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c",
+ "sha256:3eeeb0405fd145e714f7633a5173318bd88d8bbfc3dd0a5751f8c4f70ae629bc",
+ "sha256:44f60519595eaca110f248e5017363d751b12782a6f2bd6a7041cba275215f5d",
+ "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808",
+ "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828",
+ "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869",
+ "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d",
+ "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9",
+ "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0",
+ "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc",
+ "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15",
+ "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c",
+ "sha256:c11579638288e53fc94ad60022ff1b67865363e730ee41ad5e6f0a17188b327a",
+ "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3",
+ "sha256:c53af463f4a40de78c58b8b2710ade243c81cbca641e34debf3396a9640d6ec1",
+ "sha256:cb763ceceae04803adcc4e2d80d611ef201c73da32d8f2722e9d0ab0c7f10768",
+ "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d",
+ "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b",
+ "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e",
+ "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d",
+ "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730",
+ "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394",
+ "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1",
+ "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591"
+ ],
+ "version": "==1.14.3"
},
"cfgv": {
"hashes": [
"sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d",
"sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"
],
- "markers": "python_full_version >= '3.6.1'",
"version": "==3.2.0"
},
"chardet": {
@@ -400,11 +402,10 @@
},
"colorama": {
"hashes": [
- "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
- "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
+ "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
+ "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==0.4.3"
+ "version": "==0.4.4"
},
"commonmark": {
"hashes": [
@@ -455,31 +456,31 @@
},
"cryptography": {
"hashes": [
- "sha256:10c9775a3f31610cf6b694d1fe598f2183441de81cedcf1814451ae53d71b13a",
- "sha256:180c9f855a8ea280e72a5d61cf05681b230c2dce804c48e9b2983f491ecc44ed",
- "sha256:247df238bc05c7d2e934a761243bfdc67db03f339948b1e2e80c75d41fc7cc36",
- "sha256:26409a473cc6278e4c90f782cd5968ebad04d3911ed1c402fc86908c17633e08",
- "sha256:2a27615c965173c4c88f2961cf18115c08fedfb8bdc121347f26e8458dc6d237",
- "sha256:2e26223ac636ca216e855748e7d435a1bf846809ed12ed898179587d0cf74618",
- "sha256:321761d55fb7cb256b771ee4ed78e69486a7336be9143b90c52be59d7657f50f",
- "sha256:4005b38cd86fc51c955db40b0f0e52ff65340874495af72efabb1bb8ca881695",
- "sha256:4b9e96543d0784acebb70991ebc2dbd99aa287f6217546bb993df22dd361d41c",
- "sha256:548b0818e88792318dc137d8b1ec82a0ab0af96c7f0603a00bb94f896fbf5e10",
- "sha256:725875681afe50b41aee7fdd629cedbc4720bab350142b12c55c0a4d17c7416c",
- "sha256:7a63e97355f3cd77c94bd98c59cb85fe0efd76ea7ef904c9b0316b5bbfde6ed1",
- "sha256:94191501e4b4009642be21dde2a78bd3c2701a81ee57d3d3d02f1d99f8b64a9e",
- "sha256:969ae512a250f869c1738ca63be843488ff5cc031987d302c1f59c7dbe1b225f",
- "sha256:9f734423eb9c2ea85000aa2476e0d7a58e021bc34f0a373ac52a5454cd52f791",
- "sha256:b45ab1c6ece7c471f01c56f5d19818ca797c34541f0b2351635a5c9fe09ac2e0",
- "sha256:cc6096c86ec0de26e2263c228fb25ee01c3ff1346d3cfc219d67d49f303585af",
- "sha256:dc3f437ca6353979aace181f1b790f0fc79e446235b14306241633ab7d61b8f8",
- "sha256:e7563eb7bc5c7e75a213281715155248cceba88b11cb4b22957ad45b85903761",
- "sha256:e7dad66a9e5684a40f270bd4aee1906878193ae50a4831922e454a2a457f1716",
- "sha256:eb80a288e3cfc08f679f95da72d2ef90cb74f6d8a8ba69d2f215c5e110b2ca32",
- "sha256:fa7fbcc40e2210aca26c7ac8a39467eae444d90a2c346cbcffd9133a166bcc67"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==3.1"
+ "sha256:22f8251f68953553af4f9c11ec5f191198bc96cff9f0ac5dd5ff94daede0ee6d",
+ "sha256:284e275e3c099a80831f9898fb5c9559120d27675c3521278faba54e584a7832",
+ "sha256:3e17d02941c0f169c5b877597ca8be895fca0e5e3eb882526a74aa4804380a98",
+ "sha256:52a47e60953679eea0b4d490ca3c241fb1b166a7b161847ef4667dfd49e7699d",
+ "sha256:57b8c1ed13b8aa386cabbfde3be175d7b155682470b0e259fecfe53850967f8a",
+ "sha256:6a8f64ed096d13f92d1f601a92d9fd1f1025dc73a2ca1ced46dcf5e0d4930943",
+ "sha256:6e8a3c7c45101a7eeee93102500e1b08f2307c717ff553fcb3c1127efc9b6917",
+ "sha256:7ef41304bf978f33cfb6f43ca13bb0faac0c99cda33693aa20ad4f5e34e8cb8f",
+ "sha256:87c2fffd61e934bc0e2c927c3764c20b22d7f5f7f812ee1a477de4c89b044ca6",
+ "sha256:88069392cd9a1e68d2cfd5c3a2b0d72a44ef3b24b8977a4f7956e9e3c4c9477a",
+ "sha256:8a0866891326d3badb17c5fd3e02c926b635e8923fa271b4813cd4d972a57ff3",
+ "sha256:8f0fd8b0751d75c4483c534b209e39e918f0d14232c0d8a2a76e687f64ced831",
+ "sha256:9a07e6d255053674506091d63ab4270a119e9fc83462c7ab1dbcb495b76307af",
+ "sha256:9a8580c9afcdcddabbd064c0a74f337af74ff4529cdf3a12fa2e9782d677a2e5",
+ "sha256:bd80bc156d3729b38cb227a5a76532aef693b7ac9e395eea8063ee50ceed46a5",
+ "sha256:d1cbc3426e6150583b22b517ef3720036d7e3152d428c864ff0f3fcad2b97591",
+ "sha256:e15ac84dcdb89f92424cbaca4b0b34e211e7ce3ee7b0ec0e4f3c55cee65fae5a",
+ "sha256:e4789b84f8dedf190148441f7c5bfe7244782d9cbb194a36e17b91e7d3e1cca9",
+ "sha256:f01c9116bfb3ad2831e125a73dcd957d173d6ddca7701528eff1e7d97972872c",
+ "sha256:f0e3986f6cce007216b23c490f093f35ce2068f3c244051e559f647f6731b7ae",
+ "sha256:f2aa3f8ba9e2e3fd49bd3de743b976ab192fbf0eb0348cebde5d2a9de0090a9f",
+ "sha256:fb70a4cedd69dc52396ee114416a3656e011fb0311fca55eb55c7be6ed9c8aef"
+ ],
+ "index": "pypi",
+ "version": "==3.2"
},
"distlib": {
"hashes": [
@@ -491,7 +492,6 @@
"docutils": {
"hashes": [
"sha256:54a349c622ff31c91cbec43b0b512f113b5b24daf00e2ea530bb1bd9aac14849",
- "sha256:ba4584f9107571ced0d2c7f56a5499c696215ba90797849c92d395979da68521",
"sha256:d2ddba74835cb090a1b627d3de4e7835c628d07ee461f7b4480f51af2fe4d448"
],
"index": "pypi",
@@ -530,18 +530,16 @@
},
"identify": {
"hashes": [
- "sha256:c770074ae1f19e08aadbda1c886bc6d0cb55ffdc503a8c0fe8699af2fc9664ae",
- "sha256:d02d004568c5a01261839a05e91705e3e9f5c57a3551648f9b3fb2b9c62c0f62"
+ "sha256:3139bf72d81dfd785b0a464e2776bd59bdc725b4cc10e6cf46b56a0db931c82e",
+ "sha256:969d844b7a85d32a5f9ac4e163df6e846d73c87c8b75847494ee8f4bd2186421"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.5.3"
+ "version": "==1.5.6"
},
"idna": {
"hashes": [
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.10"
},
"imagesize": {
@@ -549,7 +547,6 @@
"sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1",
"sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.2.0"
},
"jeepney": {
@@ -565,7 +562,6 @@
"sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0",
"sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==2.11.2"
},
"keyring": {
@@ -573,7 +569,6 @@
"sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d",
"sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466"
],
- "markers": "python_version >= '3.6'",
"version": "==21.4.0"
},
"markupsafe": {
@@ -612,7 +607,6 @@
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.1.1"
},
"mccabe": {
@@ -642,7 +636,6 @@
"sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
"sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
],
- "markers": "python_version >= '3.5'",
"version": "==4.7.6"
},
"mypy": {
@@ -685,7 +678,6 @@
"sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
"sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.4"
},
"pathspec": {
@@ -698,10 +690,10 @@
},
"pkginfo": {
"hashes": [
- "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb",
- "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32"
+ "sha256:a6a4ac943b496745cec21f14f021bbd869d5e9b4f6ec06918cffea5a2f4b9193",
+ "sha256:ce14d7296c673dc4c61c759a0b6c14bae34e34eb819c0017bb6ca5b7292c56e9"
],
- "version": "==1.5.0.1"
+ "version": "==1.6.1"
},
"pre-commit": {
"hashes": [
@@ -716,7 +708,6 @@
"sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
"sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.6.0"
},
"pycparser": {
@@ -724,7 +715,6 @@
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.20"
},
"pyflakes": {
@@ -732,23 +722,20 @@
"sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
"sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.2.0"
},
"pygments": {
"hashes": [
- "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998",
- "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7"
+ "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0",
+ "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"
],
- "markers": "python_version >= '3.5'",
- "version": "==2.7.1"
+ "version": "==2.7.2"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
- "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.4.7"
},
"pytz": {
@@ -822,7 +809,6 @@
"sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
"sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==2.24.0"
},
"requests-toolbelt": {
@@ -849,16 +835,10 @@
},
"setuptools-scm": {
"hashes": [
- "sha256:09c659d1d6680811c43f476a33c6d3d9872416580786e96bd29ea03e6a818e41",
"sha256:69258e2eeba5f7ce1ed7a5f109519580fa3578250f8e4d6684859f86d1b15826",
- "sha256:731550a27e3901ee501c3bf99140b5436b8eeba341a9d19911cf364b8d573293",
- "sha256:892e63b4983f9e30f9e8bf89ad03d2a02a47e6e5ced09b03ae6fe952ade8a579",
- "sha256:a8994582e716ec690f33fec70cca0f85bd23ec974e3f783233e4879090a7faa8",
- "sha256:b42c150c34d6120babf3646abd7513e032be2e230b3d2034f27404c65aa0c977",
- "sha256:eaaec16b7af25c5f532b5af2332213bb6223d15cca4518f6dbc4c055641c86fd",
- "sha256:efc928d6a64162c88cdc85fa4b84adfbd6dbf9f9b04319bc495eb16dcfaae00a"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "sha256:a8994582e716ec690f33fec70cca0f85bd23ec974e3f783233e4879090a7faa8"
+ ],
+ "index": "pypi",
"version": "==4.1.2"
},
"six": {
@@ -866,7 +846,6 @@
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.15.0"
},
"snowballstemmer": {
@@ -889,7 +868,6 @@
"sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a",
"sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"
],
- "markers": "python_version >= '3.5'",
"version": "==1.0.2"
},
"sphinxcontrib-devhelp": {
@@ -897,7 +875,6 @@
"sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e",
"sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"
],
- "markers": "python_version >= '3.5'",
"version": "==1.0.2"
},
"sphinxcontrib-htmlhelp": {
@@ -905,7 +882,6 @@
"sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f",
"sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"
],
- "markers": "python_version >= '3.5'",
"version": "==1.0.3"
},
"sphinxcontrib-jsmath": {
@@ -913,7 +889,6 @@
"sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
"sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
],
- "markers": "python_version >= '3.5'",
"version": "==1.0.1"
},
"sphinxcontrib-qthelp": {
@@ -921,7 +896,6 @@
"sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72",
"sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"
],
- "markers": "python_version >= '3.5'",
"version": "==1.0.3"
},
"sphinxcontrib-serializinghtml": {
@@ -929,26 +903,22 @@
"sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc",
"sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"
],
- "markers": "python_version >= '3.5'",
"version": "==1.1.4"
},
"toml": {
"hashes": [
- "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88",
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"
+ "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
"index": "pypi",
"version": "==0.10.1"
},
"tqdm": {
"hashes": [
- "sha256:8f3c5815e3b5e20bc40463fa6b42a352178859692a68ffaa469706e6d38342a5",
- "sha256:faf9c671bd3fad5ebaeee366949d969dca2b2be32c872a7092a1e1a9048d105b"
+ "sha256:9ad44aaf0fc3697c06f6e05c7cf025dd66bc7bcb7613c66d85f4464c47ac8fad",
+ "sha256:ef54779f1c09f346b2b5a8e5c61f96fbcb639929e640e59f8cf810794f406432"
],
- "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==4.49.0"
+ "version": "==4.51.0"
},
"twine": {
"hashes": [
@@ -962,9 +932,11 @@
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
@@ -973,12 +945,16 @@
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
+ "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
@@ -996,19 +972,17 @@
},
"urllib3": {
"hashes": [
- "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a",
- "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"
+ "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
+ "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
- "version": "==1.25.10"
+ "version": "==1.25.11"
},
"virtualenv": {
"hashes": [
- "sha256:43add625c53c596d38f971a465553f6318decc39d98512bc100fa1b1e839c8dc",
- "sha256:e0305af10299a7fb0d69393d8f04cb2965dda9351140d11ac8db4e5e3970451b"
+ "sha256:b0011228208944ce71052987437d3843e05690b2f23d1c7da4263fde104c97a2",
+ "sha256:b8d6110f493af256a40d65e29846c69340a947669eec8ce784fcf3dd3af28380"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.0.31"
+ "version": "==20.1.0"
},
"webencodings": {
"hashes": [
@@ -1027,26 +1001,41 @@
},
"yarl": {
"hashes": [
- "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409",
- "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593",
- "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2",
- "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8",
- "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d",
- "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692",
- "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02",
- "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a",
- "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8",
- "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6",
- "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511",
- "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e",
- "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a",
- "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb",
- "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f",
- "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317",
- "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"
- ],
- "markers": "python_version >= '3.5'",
- "version": "==1.5.1"
+ "sha256:03b7a44384ad60be1b7be93c2a24dc74895f8d767ea0bce15b2f6fc7695a3843",
+ "sha256:076157404db9db4bb3fa9db22db319bbb36d075eeab19ba018ce20ae0cacf037",
+ "sha256:1c05ae3d5ea4287470046a2c2754f0a4c171b84ea72c8a691f776eb1753dfb91",
+ "sha256:2467baf8233f7c64048df37e11879c553943ffe7f373e689711ec2807ea13805",
+ "sha256:2bb2e21cf062dfbe985c3cd4618bae9f25271efcad9e7be1277861247eee9839",
+ "sha256:311effab3b3828ab34f0e661bb57ff422f67d5c33056298bda4c12195251f8dd",
+ "sha256:3526cb5905907f0e42bee7ef57ae4a5f02bc27dcac27859269e2bba0caa4c2b6",
+ "sha256:39b1e586f34b1d2512c9b39aa3cf24c870c972d525e36edc9ee19065db4737bb",
+ "sha256:4bed5cd7c8e69551eb19df15295ba90e62b9a6a1149c76eb4a9bab194402a156",
+ "sha256:51c6d3cf7a1f1fbe134bb92f33b7affd94d6de24cd64b466eb12de52120fb8c6",
+ "sha256:59f78b5da34ddcffb663b772f7619e296518712e022e57fc5d9f921818e2ab7c",
+ "sha256:6f29115b0c330da25a04f48612d75333bca04521181a666ca0b8761005a99150",
+ "sha256:73d4e1e1ef5e52d526c92f07d16329e1678612c6a81dd8101fdcae11a72de15c",
+ "sha256:9b48d31f8d881713fd461abfe7acbb4dcfeb47cec3056aa83f2fbcd2244577f7",
+ "sha256:a1fd575dd058e10ad4c35065e7c3007cc74d142f622b14e168d8a273a2fa8713",
+ "sha256:b3dd1052afd436ba737e61f5d3bed1f43a7f9a33fc58fbe4226eb919a7006019",
+ "sha256:b99c25ed5c355b35d1e6dae87ac7297a4844a57dc5766b173b88b6163a36eb0d",
+ "sha256:c056e86bff5a0b566e0d9fab4f67e83b12ae9cbcd250d334cbe2005bbe8c96f2",
+ "sha256:c45b49b59a5724869899798e1bbd447ac486215269511d3b76b4c235a1b766b6",
+ "sha256:cd623170c729a865037828e3f99f8ebdb22a467177a539680dfc5670b74c84e2",
+ "sha256:d25d3311794e6c71b608d7c47651c8f65eea5ab15358a27f29330b3475e8f8e5",
+ "sha256:d695439c201ed340745250f9eb4dfe8d32bf1e680c16477107b8f3ce4bff4fdb",
+ "sha256:d77f6c9133d2aabb290a7846aaa74ec14d7b5ab35b01591fac5a70c4a8c959a2",
+ "sha256:d894a2442d2cd20a3b0b0dce5a353d316c57d25a2b445e03f7eac90eee27b8af",
+ "sha256:db643ce2b58a4bd11a82348225c53c76ecdd82bb37cf4c085e6df1b676f4038c",
+ "sha256:e3a0c43a26dfed955b2a06fdc4d51d2c51bc2200aff8ce8faf14e676ea8c8862",
+ "sha256:e77bf79ad1ccae672eab22453838382fe9029fc27c8029e84913855512a587d8",
+ "sha256:f2f0174cb15435957d3b751093f89aede77df59a499ab7516bbb633b77ead13a",
+ "sha256:f3031c78edf10315abe232254e6a36b65afe65fded41ee54ed7976d0b2cdf0da",
+ "sha256:f4c007156732866aa4507d619fe6f8f2748caabed4f66b276ccd97c82572620c",
+ "sha256:f4f27ff3dd80bc7c402def211a47291ea123d59a23f59fe18fc0e81e3e71f385",
+ "sha256:f57744fc61e118b5d114ae8077d8eb9df4d2d2c11e2af194e21f0c11ed9dcf6c",
+ "sha256:f835015a825980b65356e9520979a1564c56efea7da7d4b68a14d4a07a3a7336"
+ ],
+ "version": "==1.6.2"
}
}
}
From 8c8af4f1612dc29358490a7d04dd4ff2f5d4939d Mon Sep 17 00:00:00 2001
From: Abdullah Selek
Date: Fri, 30 Oct 2020 15:24:18 +0000
Subject: [PATCH 0042/1034] Start using Python 3.9 on Travis (#1790)
* Start using Python 3.9 on Travis
* Remove allow_failures
---
.travis.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index f035343c6fb..e8d2975c5ff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,9 +28,7 @@ matrix:
- name: "3.8"
python: 3.8
- name: "3.9"
- python: 3.9-dev
- allow_failures:
- - python: 3.9-dev
+ python: 3.9
before_deploy:
- pip install pyinstaller
- pyinstaller --clean -F --add-data src/blib2to3/:blib2to3 src/black/__init__.py
From 6c3f8181854160f3db354f6f6ef3315ef05db8e7 Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Sat, 31 Oct 2020 13:42:36 -0400
Subject: [PATCH 0043/1034] Fix bug where black tries to split string on
escaped space (#1799)
Closes #1505.
---
src/black/__init__.py | 17 ++++++++++--
tests/data/long_strings__regression.py | 37 ++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 24e9d4edaaa..e09838d866a 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -3590,7 +3590,8 @@ class StringSplitter(CustomSplitMapMixin, BaseStringSplitter):
MIN_SUBSTR_SIZE characters.
The string will ONLY be split on spaces (i.e. each new substring should
- start with a space).
+ start with a space). Note that the string will NOT be split on a space
+ which is escaped with a backslash.
If the string is an f-string, it will NOT be split in the middle of an
f-expression (e.g. in f"FooBar: {foo() if x else bar()}", {foo() if x
@@ -3930,11 +3931,23 @@ def passes_all_checks(i: Index) -> bool:
section of this classes' docstring would be be met by returning @i.
"""
is_space = string[i] == " "
+
+ is_not_escaped = True
+ j = i - 1
+ while is_valid_index(j) and string[j] == "\\":
+ is_not_escaped = not is_not_escaped
+ j -= 1
+
is_big_enough = (
len(string[i:]) >= self.MIN_SUBSTR_SIZE
and len(string[:i]) >= self.MIN_SUBSTR_SIZE
)
- return is_space and is_big_enough and not breaks_fstring_expression(i)
+ return (
+ is_space
+ and is_not_escaped
+ and is_big_enough
+ and not breaks_fstring_expression(i)
+ )
# First, we check all indices BELOW @max_break_idx.
break_idx = max_break_idx
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 8290a4cbc1c..9bfb1eedd5a 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -353,6 +353,24 @@ def xxxxxxx_xxxxxx(xxxx):
key
] = "test" # set some Thrift field to non-None in the struct aa bb cc dd ee
+RE_ONE_BACKSLASH = {
+ "asdf_hjkl_jkl": re.compile(
+ r"(?
Date: Sun, 1 Nov 2020 16:17:23 -0500
Subject: [PATCH 0044/1034] Automatically build and upload binaries on release
(#1743)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit adds a new GitHub Actions workflow that builds self-contained
binaries / executables and uploads them as release assets to the triggering
release. Publishing a release, drafting one doesn't count, will trigger this
workflow.
I personally used GitHub Actions only because it's the CI/CD platform(?)
I am familiar with. Only Windows and Linux binaries are supported since
I don't have any systems running Mac OS.
For Linux, I had originally planned to use the manylinux2010 docker image
the PyPA provides for highly compatible wheel building, but unfortunately
it wasn't feasible due to GitHub Actions and PyInstaller incompatibilities.
As a stopgap the oldest versions of Linux and Windows are used although
Windows Server 2019 isn't that old nor is Ubuntu 16.04! I guess someone
(maybe me) could work out something else if compatibility is big problem.
A few things you should know about the workflow:
- You don't need to set the `GITHUB_TOKEN` secret as it is automatically
provided by GitHub.
- matrix.pathsep is used because PyInstaller configuration's format is OS
dependent for some reason ...
Also it's worth mentioning that Black once had Travis CI and AppVeyor
configuration that did the same thing as this commit. They were committed
in mid 2018 and worked (somewhat) well. Eventually we stopped using AppVeyor
and the refactor to packages broke the Travis CI config. This commit
replaces the still existing and broken Travis CI config wholesale.
Co-authored-by: Anders Fredrik Kiær <31612826+anders-kiaer@users.noreply.github.com>
- Anders told me that I could get the release asset upload URL directly
from the github.event.release payload. I originally planned to use
bruceadams/get-release to get such URL.
---
.github/workflows/upload_binary.yml | 51 +++++++++++++++++++++++++++++
.travis.yml | 14 --------
CHANGES.md | 5 +++
3 files changed, 56 insertions(+), 14 deletions(-)
create mode 100644 .github/workflows/upload_binary.yml
diff --git a/.github/workflows/upload_binary.yml b/.github/workflows/upload_binary.yml
new file mode 100644
index 00000000000..46d92ab2149
--- /dev/null
+++ b/.github/workflows/upload_binary.yml
@@ -0,0 +1,51 @@
+name: Upload self-contained binaries
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.7]
+ os: [ubuntu-16.04, windows-2019]
+ include:
+ - os: windows-2019
+ pathsep: ";"
+ executable_suffix: ".exe"
+ executable_mime: "application/vnd.microsoft.portable-executable"
+ - os: ubuntu-16.04
+ pathsep: ":"
+ executable_suffix: ".elf"
+ executable_mime: "application/x-executable"
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip wheel setuptools
+ python -m pip install .
+ python -m pip install pyinstaller
+
+ - name: Build binary
+ run: |
+ python -m PyInstaller -F --name black${{ matrix.executable_suffix }} --add-data 'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
+
+ - name: Upload binary as release asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ github.event.release.upload_url }}
+ asset_path: dist/black${{ matrix.executable_suffix }}
+ asset_name: black${{ matrix.executable_suffix }}
+ asset_content_type: ${{ matrix.executable_mime }}
diff --git a/.travis.yml b/.travis.yml
index e8d2975c5ff..e782272e813 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,17 +29,3 @@ matrix:
python: 3.8
- name: "3.9"
python: 3.9
-before_deploy:
- - pip install pyinstaller
- - pyinstaller --clean -F --add-data src/blib2to3/:blib2to3 src/black/__init__.py
-deploy:
- provider: releases
- api_key:
- secure: chYvcmnRqRKtfBcAZRj62rEv0ziWuHMl6MnfQbd1MOVQ4njntI8+CCPk118dW6MWSfwTqyMFy+t9gAgQYhjkLEHMS2aK9Z2wCWki1MkBrkMw5tYoLFvPu0KQ9rIVihxsr93a/am6Oh/Hp+1uuc4zWPUf1ubX+QlCzsxjCzVso1kTJjjdN04UxvkcFR+sY2d9Qyy9WcdifChnLwdmIJKIoVOE7Imm820nzImJHkJh8iSnjBjL98gvPPeC/nWTltsbErvf2mCv4NIjzjQZvHa87c7rSJGbliNrAxCSyyvBX+JNeS8U2fGLE83do0HieyjdPbTuc27e2nsrrihgPh+hXbiJerljclfp5hsJ5qGz5sS9MU1fR7sSLiQQ2v0TYB5RRwd34TgGiLwFAZZmgZOfMUCtefCKvP8qvELMSNd99+msfPEHiuhADF0bKPTbCUa6BgUHNr6woOLmHerjPHd6NI/a8Skz/uQB4xr3spLSmfUmX0fEqyYUDphkGPNH8IsvC1/F2isecW9kOzEWmB5oCmpMTGm4TIf3C01Nx+9PVwB2Z+30hhbfIEBxD4loRFmh/hU5TIQEpneF8yoIfe9EnMaoZbq86xhADZXvLIZvpXUdm1NQZDG6na2S1fwyOUKQsW6BWLcfoZZwZlrXrViD1jBsHBV++s+lxShTeTCszlo=
- file:
- - dist/black
- skip_cleanup: true
- on:
- condition: $TRAVIS_PYTHON_VERSION == '3.6'
- repo: psf/black
- tags: true
diff --git a/CHANGES.md b/CHANGES.md
index dfc54224b41..240abe302a4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -21,6 +21,11 @@
- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+#### _Packaging_
+
+- Self-contained native _Black_ binaries are now provided for releases via GitHub
+ Releases (#1743)
+
### 20.8b1
#### _Packaging_
From edf1c9dc0f20239b9d5351d8b0607c9e936dd43f Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Fri, 6 Nov 2020 19:17:23 -0500
Subject: [PATCH 0045/1034] Fix bug which causes f-expressions to be split
(#1809)
Closes #1807.
---
src/black/__init__.py | 5 +++--
tests/data/long_strings__regression.py | 14 ++++++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index e09838d866a..7a7456ad78b 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -3611,13 +3611,14 @@ class StringSplitter(CustomSplitMapMixin, BaseStringSplitter):
MIN_SUBSTR_SIZE = 6
# Matches an "f-expression" (e.g. {var}) that might be found in an f-string.
RE_FEXPR = r"""
- (? TMatchResult:
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 9bfb1eedd5a..7065b2fcef8 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -371,6 +371,10 @@ def xxxxxxx_xxxxxx(xxxx):
),
}
+# We do NOT split on f-string expressions.
+print(f"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam. {[f'{i}' for i in range(10)]}")
+x = f"This is a long string which contains an f-expr that should not split {{{[i for i in range(5)]}}}."
+
# output
@@ -830,3 +834,13 @@ def xxxxxxx_xxxxxx(xxxx):
r"(?
Date: Mon, 9 Nov 2020 14:58:23 -0500
Subject: [PATCH 0046/1034] Correctly handle inline tabs in docstrings (#1810)
The `fix_docstring` function expanded all tabs, which caused a
difference in the AST representation when those tabs were inline and not
leading. This changes the function to only expand leading tabs so inline
tabs are preserved.
Fixes #1601.
---
src/black/__init__.py | 26 +++++++++++++++++---
tests/data/docstring.py | 53 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 7a7456ad78b..7e13a5d33f5 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -6744,13 +6744,33 @@ def is_docstring(leaf: Leaf) -> bool:
return False
+def lines_with_leading_tabs_expanded(s: str) -> List[str]:
+ """
+ Splits string into lines and expands only leading tabs (following the normal
+ Python rules)
+ """
+ lines = []
+ for line in s.splitlines():
+ # Find the index of the first non-whitespace character after a string of
+ # whitespace that includes at least one tab
+ match = re.match(r"\s*\t+\s*(\S)", line)
+ if match:
+ first_non_whitespace_idx = match.start(1)
+
+ lines.append(
+ line[:first_non_whitespace_idx].expandtabs()
+ + line[first_non_whitespace_idx:]
+ )
+ else:
+ lines.append(line)
+ return lines
+
+
def fix_docstring(docstring: str, prefix: str) -> str:
# https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation
if not docstring:
return ""
- # Convert tabs to spaces (following the normal Python rules)
- # and split into a list of lines:
- lines = docstring.expandtabs().splitlines()
+ lines = lines_with_leading_tabs_expanded(docstring)
# Determine minimum indentation (first line doesn't count):
indent = sys.maxsize
for line in lines[1:]:
diff --git a/tests/data/docstring.py b/tests/data/docstring.py
index 2d3d73a101c..5c6985d0e08 100644
--- a/tests/data/docstring.py
+++ b/tests/data/docstring.py
@@ -110,6 +110,32 @@ def ignored_docstring():
"""a => \
b"""
+
+def docstring_with_inline_tabs_and_space_indentation():
+ """hey
+
+ tab separated value
+ tab at start of line and then a tab separated value
+ multiple tabs at the beginning and inline
+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
+
+ line ends with some tabs
+ """
+
+
+def docstring_with_inline_tabs_and_tab_indentation():
+ """hey
+
+ tab separated value
+ tab at start of line and then a tab separated value
+ multiple tabs at the beginning and inline
+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
+
+ line ends with some tabs
+ """
+ pass
+
+
# output
class MyClass:
@@ -222,4 +248,29 @@ def believe_it_or_not_this_is_in_the_py_stdlib():
def ignored_docstring():
"""a => \
-b"""
\ No newline at end of file
+b"""
+
+
+def docstring_with_inline_tabs_and_space_indentation():
+ """hey
+
+ tab separated value
+ tab at start of line and then a tab separated value
+ multiple tabs at the beginning and inline
+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
+
+ line ends with some tabs
+ """
+
+
+def docstring_with_inline_tabs_and_tab_indentation():
+ """hey
+
+ tab separated value
+ tab at start of line and then a tab separated value
+ multiple tabs at the beginning and inline
+ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
+
+ line ends with some tabs
+ """
+ pass
From 7d032fa848c8910007a0a41c1ba61d70d2846f48 Mon Sep 17 00:00:00 2001
From: Casper Weiss Bang
Date: Fri, 13 Nov 2020 16:25:17 +0100
Subject: [PATCH 0047/1034] Use lowercase hex numbers fixes #1692 (#1775)
* Made hex lower case
* Refactored numeric formatting section
* Redid some refactoring and removed bloat
* Removed additions from test_requirements.txt
* Primer now expects expected changes
* Undid some refactoring
* added to changelog
* Update src/black/__init__.py
Co-authored-by: Zsolt Dollenstein
Co-authored-by: Zsolt Dollenstein
Co-authored-by: Cooper Lees
---
.gitignore | 3 +-
CHANGES.md | 2 +
src/black/__init__.py | 57 +++++++++++++------
src/black_primer/primer.json | 10 ++--
src/blib2to3/pytree.py | 2 +-
test_requirements.txt | 2 +-
tests/data/numeric_literals.py | 4 +-
tests/data/numeric_literals_py2.py | 4 +-
.../data/numeric_literals_skip_underscores.py | 6 +-
9 files changed, 57 insertions(+), 33 deletions(-)
diff --git a/.gitignore b/.gitignore
index 3207e72ae28..30225ec7764 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.venv
.coverage
_build
.DS_Store
@@ -15,4 +16,4 @@ src/_black_version.py
.dmypy.json
*.swp
.hypothesis/
-venv/
\ No newline at end of file
+venv/
diff --git a/CHANGES.md b/CHANGES.md
index 240abe302a4..67697bd7b07 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -21,6 +21,8 @@
- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+- use lowercase hex strings (#1692)
+
#### _Packaging_
- Self-contained native _Black_ binaries are now provided for releases via GitHub
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 7e13a5d33f5..44edeb0d9f1 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -5192,31 +5192,52 @@ def normalize_numeric_literal(leaf: Leaf) -> None:
# Leave octal and binary literals alone.
pass
elif text.startswith("0x"):
- # Change hex literals to upper case.
- before, after = text[:2], text[2:]
- text = f"{before}{after.upper()}"
+ text = format_hex(text)
elif "e" in text:
- before, after = text.split("e")
- sign = ""
- if after.startswith("-"):
- after = after[1:]
- sign = "-"
- elif after.startswith("+"):
- after = after[1:]
- before = format_float_or_int_string(before)
- text = f"{before}e{sign}{after}"
+ text = format_scientific_notation(text)
elif text.endswith(("j", "l")):
- number = text[:-1]
- suffix = text[-1]
- # Capitalize in "2L" because "l" looks too similar to "1".
- if suffix == "l":
- suffix = "L"
- text = f"{format_float_or_int_string(number)}{suffix}"
+ text = format_long_or_complex_number(text)
else:
text = format_float_or_int_string(text)
leaf.value = text
+def format_hex(text: str) -> str:
+ """
+ Formats a hexadecimal string like "0x12b3"
+
+ Uses lowercase because of similarity between "B" and "8", which
+ can cause security issues.
+ see: https://github.com/psf/black/issues/1692
+ """
+
+ before, after = text[:2], text[2:]
+ return f"{before}{after.lower()}"
+
+
+def format_scientific_notation(text: str) -> str:
+ """Formats a numeric string utilizing scentific notation"""
+ before, after = text.split("e")
+ sign = ""
+ if after.startswith("-"):
+ after = after[1:]
+ sign = "-"
+ elif after.startswith("+"):
+ after = after[1:]
+ before = format_float_or_int_string(before)
+ return f"{before}e{sign}{after}"
+
+
+def format_long_or_complex_number(text: str) -> str:
+ """Formats a long or complex string like `10L` or `10j`"""
+ number = text[:-1]
+ suffix = text[-1]
+ # Capitalize in "2L" because "l" looks too similar to "1".
+ if suffix == "l":
+ suffix = "L"
+ return f"{format_float_or_int_string(number)}{suffix}"
+
+
def format_float_or_int_string(text: str) -> str:
"""Formats a float string like "1.0"."""
if "." not in text:
diff --git a/src/black_primer/primer.json b/src/black_primer/primer.json
index cdc863ca032..32df01571a7 100644
--- a/src/black_primer/primer.json
+++ b/src/black_primer/primer.json
@@ -10,7 +10,7 @@
},
"attrs": {
"cli_arguments": [],
- "expect_formatting_changes": false,
+ "expect_formatting_changes": true,
"git_clone_url": "https://github.com/python-attrs/attrs.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -47,7 +47,7 @@
},
"hypothesis": {
"cli_arguments": [],
- "expect_formatting_changes": false,
+ "expect_formatting_changes": true,
"git_clone_url": "https://github.com/HypothesisWorks/hypothesis.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -63,7 +63,7 @@
},
"pillow": {
"cli_arguments": [],
- "expect_formatting_changes": false,
+ "expect_formatting_changes": true,
"git_clone_url": "https://github.com/python-pillow/Pillow.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -77,7 +77,7 @@
},
"pyramid": {
"cli_arguments": [],
- "expect_formatting_changes": false,
+ "expect_formatting_changes": true,
"git_clone_url": "https://github.com/Pylons/pyramid.git",
"long_checkout": false,
"py_versions": ["all"]
@@ -112,7 +112,7 @@
},
"virtualenv": {
"cli_arguments": [],
- "expect_formatting_changes": false,
+ "expect_formatting_changes": true,
"git_clone_url": "https://github.com/pypa/virtualenv.git",
"long_checkout": false,
"py_versions": ["all"]
diff --git a/src/blib2to3/pytree.py b/src/blib2to3/pytree.py
index 4b841b768e7..6dba3c7bb15 100644
--- a/src/blib2to3/pytree.py
+++ b/src/blib2to3/pytree.py
@@ -34,7 +34,7 @@
import sys
from io import StringIO
-HUGE: int = 0x7FFFFFFF # maximum repeat count, default max
+HUGE: int = 0x7fffffff # maximum repeat count, default max
_type_reprs: Dict[int, Union[Text, int]] = {}
diff --git a/test_requirements.txt b/test_requirements.txt
index 3e65cdb669f..9f69b8edf83 100644
--- a/test_requirements.txt
+++ b/test_requirements.txt
@@ -2,4 +2,4 @@ pytest >= 6.1.1
pytest-mock >= 3.3.1
pytest-cases >= 2.3.0
coverage >= 5.3
-parameterized >= 0.7.4
\ No newline at end of file
+parameterized >= 0.7.4
diff --git a/tests/data/numeric_literals.py b/tests/data/numeric_literals.py
index 254da68d330..06b7f7758ee 100644
--- a/tests/data/numeric_literals.py
+++ b/tests/data/numeric_literals.py
@@ -12,7 +12,7 @@
x = 123456789E123456789
x = 123456789J
x = 123456789.123456789J
-x = 0XB1ACC
+x = 0Xb1aCc
x = 0B1011
x = 0O777
x = 0.000000006
@@ -36,7 +36,7 @@
x = 123456789e123456789
x = 123456789j
x = 123456789.123456789j
-x = 0xB1ACC
+x = 0xb1acc
x = 0b1011
x = 0o777
x = 0.000000006
diff --git a/tests/data/numeric_literals_py2.py b/tests/data/numeric_literals_py2.py
index 8f85c43f265..8b2c7faa306 100644
--- a/tests/data/numeric_literals_py2.py
+++ b/tests/data/numeric_literals_py2.py
@@ -3,7 +3,7 @@
x = 123456789L
x = 123456789l
x = 123456789
-x = 0xb1acc
+x = 0xB1aCc
# output
@@ -13,4 +13,4 @@
x = 123456789L
x = 123456789L
x = 123456789
-x = 0xB1ACC
+x = 0xb1acc
diff --git a/tests/data/numeric_literals_skip_underscores.py b/tests/data/numeric_literals_skip_underscores.py
index e345bb90276..f83e23312f2 100644
--- a/tests/data/numeric_literals_skip_underscores.py
+++ b/tests/data/numeric_literals_skip_underscores.py
@@ -3,7 +3,7 @@
x = 123456789
x = 1_2_3_4_5_6_7
x = 1E+1
-x = 0xb1acc
+x = 0xb1AcC
x = 0.00_00_006
x = 12_34_567J
x = .1_2
@@ -16,8 +16,8 @@
x = 123456789
x = 1_2_3_4_5_6_7
x = 1e1
-x = 0xB1ACC
+x = 0xb1acc
x = 0.00_00_006
x = 12_34_567j
x = 0.1_2
-x = 1_2.0
\ No newline at end of file
+x = 1_2.0
From dea81b7ad5cfa04c3572771c34af823449d0a8f3 Mon Sep 17 00:00:00 2001
From: Thiago Bellini Ribeiro
Date: Fri, 13 Nov 2020 12:26:07 -0300
Subject: [PATCH 0048/1034] Provide a stdin-filename to allow stdin to respect
force-exclude rules (#1780)
* Provide a stdin-filename to allow stdin to respect exclude/force-exclude rules
This will allow automatic tools to enforce the project's
exclude/force-exclude rules even if they pass the file through stdin to
update its buffer.
This is a similar solution to --stdin-display-name in flake8.
* Update src/black/__init__.py
Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com>
* --stdin-filename should only respect --exclude-filename
* Update README with the new --stdin-filename option
* Write some tests for the new stdin-filename functionality
* Apply suggestions from code review
Co-authored-by: Hugo van Kemenade
* Force stdin output when we asked for stdin even if the file exists
* Add an entry in the changelog regarding --stdin-filename
* Reduce disk reads if possible
Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com>
* Check for is_stdin and p.is_file before checking for p.is_dir()
Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade
---
README.md | 5 ++
docs/change_log.md | 3 +
src/black/__init__.py | 67 +++++++++++++-----
tests/test_black.py | 159 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 217 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
index d34ce146e0d..a557a6fc6c8 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,11 @@ Options:
matching this regex will be excluded even
when they are passed explicitly as arguments.
+ --stdin-filename TEXT The name of the file when passing it through
+ stdin. Useful to make sure Black will respect
+ --force-exclude option on some editors that
+ rely on using stdin.
+
-q, --quiet Don't emit non-error messages to stderr.
Errors are still emitted; silence those with
2>/dev/null.
diff --git a/docs/change_log.md b/docs/change_log.md
index 1ee35a4d8f9..e6afefbf686 100644
--- a/docs/change_log.md
+++ b/docs/change_log.md
@@ -23,6 +23,9 @@
- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+- Added `--stdin-filename` argument to allow stdin to respect `--force-exclude` rules.
+ Works very alike to flake8's `--stdin-display-name` (#1780)
+
### 20.8b1
#### _Packaging_
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 44edeb0d9f1..48690573810 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -68,6 +68,7 @@
DEFAULT_EXCLUDES = r"/(\.direnv|\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist)/" # noqa: B950
DEFAULT_INCLUDES = r"\.pyi?$"
CACHE_DIR = Path(user_cache_dir("black", version=__version__))
+STDIN_PLACEHOLDER = "__BLACK_STDIN_FILENAME__"
STRING_PREFIX_CHARS: Final = "furbFURB" # All possible string prefix characters.
@@ -457,6 +458,15 @@ def target_version_option_callback(
"excluded even when they are passed explicitly as arguments."
),
)
+@click.option(
+ "--stdin-filename",
+ type=str,
+ help=(
+ "The name of the file when passing it through stdin. Useful to make "
+ "sure Black will respect --force-exclude option on some "
+ "editors that rely on using stdin."
+ ),
+)
@click.option(
"-q",
"--quiet",
@@ -516,6 +526,7 @@ def main(
include: str,
exclude: str,
force_exclude: Optional[str],
+ stdin_filename: Optional[str],
src: Tuple[str, ...],
config: Optional[str],
) -> None:
@@ -548,6 +559,7 @@ def main(
exclude=exclude,
force_exclude=force_exclude,
report=report,
+ stdin_filename=stdin_filename,
)
path_empty(
@@ -587,6 +599,7 @@ def get_sources(
exclude: str,
force_exclude: Optional[str],
report: "Report",
+ stdin_filename: Optional[str],
) -> Set[Path]:
"""Compute the set of files to be formatted."""
try:
@@ -613,22 +626,14 @@ def get_sources(
gitignore = get_gitignore(root)
for s in src:
- p = Path(s)
- if p.is_dir():
- sources.update(
- gen_python_files(
- p.iterdir(),
- root,
- include_regex,
- exclude_regex,
- force_exclude_regex,
- report,
- gitignore,
- )
- )
- elif s == "-":
- sources.add(p)
- elif p.is_file():
+ if s == "-" and stdin_filename:
+ p = Path(stdin_filename)
+ is_stdin = True
+ else:
+ p = Path(s)
+ is_stdin = False
+
+ if is_stdin or p.is_file():
normalized_path = normalize_path_maybe_ignore(p, root, report)
if normalized_path is None:
continue
@@ -643,6 +648,23 @@ def get_sources(
report.path_ignored(p, "matches the --force-exclude regular expression")
continue
+ if is_stdin:
+ p = Path(f"{STDIN_PLACEHOLDER}{str(p)}")
+
+ sources.add(p)
+ elif p.is_dir():
+ sources.update(
+ gen_python_files(
+ p.iterdir(),
+ root,
+ include_regex,
+ exclude_regex,
+ force_exclude_regex,
+ report,
+ gitignore,
+ )
+ )
+ elif s == "-":
sources.add(p)
else:
err(f"invalid path: {s}")
@@ -670,7 +692,18 @@ def reformat_one(
"""
try:
changed = Changed.NO
- if not src.is_file() and str(src) == "-":
+
+ if str(src) == "-":
+ is_stdin = True
+ elif str(src).startswith(STDIN_PLACEHOLDER):
+ is_stdin = True
+ # Use the original name again in case we want to print something
+ # to the user
+ src = Path(str(src)[len(STDIN_PLACEHOLDER) :])
+ else:
+ is_stdin = False
+
+ if is_stdin:
if format_stdin_to_stdout(fast=fast, write_back=write_back, mode=mode):
changed = Changed.YES
else:
diff --git a/tests/test_black.py b/tests/test_black.py
index b0cf6ed5caa..a688c8780ef 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1336,10 +1336,169 @@ def test_exclude_for_issue_1572(self) -> None:
exclude=exclude,
force_exclude=None,
report=report,
+ stdin_filename=None,
)
)
self.assertEqual(sorted(expected), sorted(sources))
+ @patch("black.find_project_root", lambda *args: THIS_DIR.resolve())
+ def test_get_sources_with_stdin(self) -> None:
+ include = ""
+ exclude = r"/exclude/|a\.py"
+ src = "-"
+ report = black.Report()
+ expected = [Path("-")]
+ sources = list(
+ black.get_sources(
+ ctx=FakeContext(),
+ src=(src,),
+ quiet=True,
+ verbose=False,
+ include=include,
+ exclude=exclude,
+ force_exclude=None,
+ report=report,
+ stdin_filename=None,
+ )
+ )
+ self.assertEqual(sorted(expected), sorted(sources))
+
+ @patch("black.find_project_root", lambda *args: THIS_DIR.resolve())
+ def test_get_sources_with_stdin_filename(self) -> None:
+ include = ""
+ exclude = r"/exclude/|a\.py"
+ src = "-"
+ report = black.Report()
+ stdin_filename = str(THIS_DIR / "data/collections.py")
+ expected = [Path(f"__BLACK_STDIN_FILENAME__{stdin_filename}")]
+ sources = list(
+ black.get_sources(
+ ctx=FakeContext(),
+ src=(src,),
+ quiet=True,
+ verbose=False,
+ include=include,
+ exclude=exclude,
+ force_exclude=None,
+ report=report,
+ stdin_filename=stdin_filename,
+ )
+ )
+ self.assertEqual(sorted(expected), sorted(sources))
+
+ @patch("black.find_project_root", lambda *args: THIS_DIR.resolve())
+ def test_get_sources_with_stdin_filename_and_exclude(self) -> None:
+ # Exclude shouldn't exclude stdin_filename since it is mimicing the
+ # file being passed directly. This is the same as
+ # test_exclude_for_issue_1572
+ path = THIS_DIR / "data" / "include_exclude_tests"
+ include = ""
+ exclude = r"/exclude/|a\.py"
+ src = "-"
+ report = black.Report()
+ stdin_filename = str(path / "b/exclude/a.py")
+ expected = [Path(f"__BLACK_STDIN_FILENAME__{stdin_filename}")]
+ sources = list(
+ black.get_sources(
+ ctx=FakeContext(),
+ src=(src,),
+ quiet=True,
+ verbose=False,
+ include=include,
+ exclude=exclude,
+ force_exclude=None,
+ report=report,
+ stdin_filename=stdin_filename,
+ )
+ )
+ self.assertEqual(sorted(expected), sorted(sources))
+
+ @patch("black.find_project_root", lambda *args: THIS_DIR.resolve())
+ def test_get_sources_with_stdin_filename_and_force_exclude(self) -> None:
+ # Force exclude should exclude the file when passing it through
+ # stdin_filename
+ path = THIS_DIR / "data" / "include_exclude_tests"
+ include = ""
+ force_exclude = r"/exclude/|a\.py"
+ src = "-"
+ report = black.Report()
+ stdin_filename = str(path / "b/exclude/a.py")
+ sources = list(
+ black.get_sources(
+ ctx=FakeContext(),
+ src=(src,),
+ quiet=True,
+ verbose=False,
+ include=include,
+ exclude="",
+ force_exclude=force_exclude,
+ report=report,
+ stdin_filename=stdin_filename,
+ )
+ )
+ self.assertEqual([], sorted(sources))
+
+ def test_reformat_one_with_stdin(self) -> None:
+ with patch(
+ "black.format_stdin_to_stdout",
+ return_value=lambda *args, **kwargs: black.Changed.YES,
+ ) as fsts:
+ report = MagicMock()
+ path = Path("-")
+ black.reformat_one(
+ path,
+ fast=True,
+ write_back=black.WriteBack.YES,
+ mode=DEFAULT_MODE,
+ report=report,
+ )
+ fsts.assert_called_once()
+ report.done.assert_called_with(path, black.Changed.YES)
+
+ def test_reformat_one_with_stdin_filename(self) -> None:
+ with patch(
+ "black.format_stdin_to_stdout",
+ return_value=lambda *args, **kwargs: black.Changed.YES,
+ ) as fsts:
+ report = MagicMock()
+ p = "foo.py"
+ path = Path(f"__BLACK_STDIN_FILENAME__{p}")
+ expected = Path(p)
+ black.reformat_one(
+ path,
+ fast=True,
+ write_back=black.WriteBack.YES,
+ mode=DEFAULT_MODE,
+ report=report,
+ )
+ fsts.assert_called_once()
+ # __BLACK_STDIN_FILENAME__ should have been striped
+ report.done.assert_called_with(expected, black.Changed.YES)
+
+ def test_reformat_one_with_stdin_and_existing_path(self) -> None:
+ with patch(
+ "black.format_stdin_to_stdout",
+ return_value=lambda *args, **kwargs: black.Changed.YES,
+ ) as fsts:
+ report = MagicMock()
+ # Even with an existing file, since we are forcing stdin, black
+ # should output to stdout and not modify the file inplace
+ p = Path(str(THIS_DIR / "data/collections.py"))
+ # Make sure is_file actually returns True
+ self.assertTrue(p.is_file())
+ path = Path(f"__BLACK_STDIN_FILENAME__{p}")
+ expected = Path(p)
+ black.reformat_one(
+ path,
+ fast=True,
+ write_back=black.WriteBack.YES,
+ mode=DEFAULT_MODE,
+ report=report,
+ )
+ fsts.assert_called_once()
+ # __BLACK_STDIN_FILENAME__ should have been striped
+ report.done.assert_called_with(expected, black.Changed.YES)
+
def test_gitignore_exclude(self) -> None:
path = THIS_DIR / "data" / "include_exclude_tests"
include = re.compile(r"\.pyi?$")
From 4d03716eaea58ee38d77cf2bba0a72b7a27ec9fa Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Tue, 24 Nov 2020 04:39:25 -0500
Subject: [PATCH 0049/1034] Allow same RHS expressions in annotated assignments
as in regular assignments (#1835)
---
CHANGES.md | 3 +++
src/blib2to3/Grammar.txt | 2 +-
tests/data/python38.py | 18 ++++++++++++++++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/CHANGES.md b/CHANGES.md
index 67697bd7b07..ca8a0472a3b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -21,6 +21,9 @@
- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
+- Added parsing support for unparenthesized tuples and yield expressions in annotated
+ assignments (#1835)
+
- use lowercase hex strings (#1692)
#### _Packaging_
diff --git a/src/blib2to3/Grammar.txt b/src/blib2to3/Grammar.txt
index eafaee84cb3..69b9af96608 100644
--- a/src/blib2to3/Grammar.txt
+++ b/src/blib2to3/Grammar.txt
@@ -77,7 +77,7 @@ small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | exec_stmt | assert_stmt)
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
-annassign: ':' test ['=' test]
+annassign: ':' test ['=' (yield_expr|testlist_star_expr)]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
diff --git a/tests/data/python38.py b/tests/data/python38.py
index 1a7f76167d9..63b0588bc27 100644
--- a/tests/data/python38.py
+++ b/tests/data/python38.py
@@ -11,6 +11,14 @@ def starred_yield():
yield "value1", *my_list
+# all right hand side expressions allowed in regular assignments are now also allowed in
+# annotated assignments
+a : Tuple[ str, int] = "1", 2
+a: Tuple[int , ... ] = b, *c, d
+def t():
+ a : str = yield "a"
+
+
# output
@@ -25,3 +33,13 @@ def starred_return():
def starred_yield():
my_list = ["value2", "value3"]
yield "value1", *my_list
+
+
+# all right hand side expressions allowed in regular assignments are now also allowed in
+# annotated assignments
+a: Tuple[str, int] = "1", 2
+a: Tuple[int, ...] = b, *c, d
+
+
+def t():
+ a: str = yield "a"
From 7f75fe3669ebf0627b1b0476a6d02047e909b959 Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Wed, 25 Nov 2020 19:26:35 -0500
Subject: [PATCH 0050/1034] Switch back to Python 3.8 for ReadTheDocs (#1839)
ReadTheDocs doesn't support Python 3.9 yet.
---
readthedocs.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readthedocs.yml b/readthedocs.yml
index 32bcf1fa50e..15065033d0f 100644
--- a/readthedocs.yml
+++ b/readthedocs.yml
@@ -1,6 +1,6 @@
version: 2
python:
- version: 3.9
+ version: 3.8
install:
- requirements: docs/requirements.txt
- method: setuptools
From 2989dc1bf822b1b2a6bd250cea37bbf20c237764 Mon Sep 17 00:00:00 2001
From: Noel Evans
Date: Wed, 9 Dec 2020 23:40:45 +0000
Subject: [PATCH 0051/1034] vim plugin: Add quiet flag so non-error actions go
unreported (#1733)
---
docs/editor_integration.md | 1 +
plugin/black.vim | 11 +++++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/docs/editor_integration.md b/docs/editor_integration.md
index 21a6865d60e..037b265b9a0 100644
--- a/docs/editor_integration.md
+++ b/docs/editor_integration.md
@@ -123,6 +123,7 @@ Configuration:
- `g:black_linelength` (defaults to `88`)
- `g:black_skip_string_normalization` (defaults to `0`)
- `g:black_virtualenv` (defaults to `~/.vim/black` or `~/.local/share/nvim/black`)
+- `g:black_quiet` (defaults to `0`)
To install with [vim-plug](https://github.com/junegunn/vim-plug):
diff --git a/plugin/black.vim b/plugin/black.vim
index 3dd3f2151c3..c5f0313f4ac 100644
--- a/plugin/black.vim
+++ b/plugin/black.vim
@@ -48,6 +48,9 @@ if !exists("g:black_string_normalization")
let g:black_string_normalization = 1
endif
endif
+if !exists("g:black_quiet")
+ let g:black_quiet = 0
+endif
python3 << EndPython3
import collections
@@ -74,6 +77,7 @@ FLAGS = [
Flag(name="line_length", cast=int),
Flag(name="fast", cast=strtobool),
Flag(name="string_normalization", cast=strtobool),
+ Flag(name="quiet", cast=strtobool),
]
@@ -156,6 +160,7 @@ def Black():
string_normalization=configs["string_normalization"],
is_pyi=vim.current.buffer.name.endswith('.pyi'),
)
+ quiet = configs["quiet"]
buffer_str = '\n'.join(vim.current.buffer) + '\n'
try:
@@ -165,7 +170,8 @@ def Black():
mode=mode,
)
except black.NothingChanged:
- print(f'Already well formatted, good job. (took {time.time() - start:.4f}s)')
+ if not quiet:
+ print(f'Already well formatted, good job. (took {time.time() - start:.4f}s)')
except Exception as exc:
print(exc)
else:
@@ -183,7 +189,8 @@ def Black():
window.cursor = cursor
except vim.error:
window.cursor = (len(window.buffer), 0)
- print(f'Reformatted in {time.time() - start:.4f}s.')
+ if not quiet:
+ print(f'Reformatted in {time.time() - start:.4f}s.')
def get_configs():
path_pyproject_toml = black.find_pyproject_toml(vim.eval("fnamemodify(getcwd(), ':t')"))
From a522aa45c65bb896637d0add27b4c2a9fec6b976 Mon Sep 17 00:00:00 2001
From: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Date: Sun, 13 Dec 2020 23:20:25 -0800
Subject: [PATCH 0052/1034] Remove all trace of flake8-mypy (#1867)
flake8-mypy is long dead and shouldn't be used, see
https://github.com/ambv/flake8-mypy. We appear to use pre-commit to run
mypy now anyway.
I ran `pipenv uninstall flake8-mypy`, which seems to have made several
changes to Pipfile.lock. Let me know if there's a better way to do this.
Co-authored-by: hauntsaninja <>
---
Pipfile | 1 -
Pipfile.lock | 842 +++++++++++++++++++++++++++++----------------------
mypy.ini | 1 -
3 files changed, 473 insertions(+), 371 deletions(-)
diff --git a/Pipfile b/Pipfile
index 1ced1ed096b..ba596b3d738 100644
--- a/Pipfile
+++ b/Pipfile
@@ -9,7 +9,6 @@ coverage = "*"
docutils = "==0.15" # not a direct dependency, see https://github.com/pypa/pipenv/issues/3865
flake8 = "*"
flake8-bugbear = "*"
-flake8-mypy = "*"
mypy = ">=0.782"
pre-commit = "*"
readme_renderer = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index 95b7613114a..a5c38aa0777 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "46390803c9b9e1b77a1b4a29de602d864dea188488d3aee6361030c91529611c"
+ "sha256": "21836c0a63b6e3e1eacd0adec7dea61d2d5989e38225edd976ff144e499f0426"
},
"pipfile-spec": 6,
"requires": {},
@@ -16,21 +16,46 @@
"default": {
"aiohttp": {
"hashes": [
- "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e",
- "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326",
- "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a",
- "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654",
- "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a",
- "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4",
- "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17",
- "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec",
- "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd",
- "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48",
- "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59",
- "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"
+ "sha256:0b795072bb1bf87b8620120a6373a3c61bfcb8da7e5c2377f4bb23ff4f0b62c9",
+ "sha256:0d438c8ca703b1b714e82ed5b7a4412c82577040dadff479c08405e2a715564f",
+ "sha256:16a3cb5df5c56f696234ea9e65e227d1ebe9c18aa774d36ff42f532139066a5f",
+ "sha256:1edfd82a98c5161497bbb111b2b70c0813102ad7e0aa81cbeb34e64c93863005",
+ "sha256:2406dc1dda01c7f6060ab586e4601f18affb7a6b965c50a8c90ff07569cf782a",
+ "sha256:2858b2504c8697beb9357be01dc47ef86438cc1cb36ecb6991796d19475faa3e",
+ "sha256:2a7b7640167ab536c3cb90cfc3977c7094f1c5890d7eeede8b273c175c3910fd",
+ "sha256:3228b7a51e3ed533f5472f54f70fd0b0a64c48dc1649a0f0e809bec312934d7a",
+ "sha256:328b552513d4f95b0a2eea4c8573e112866107227661834652a8984766aa7656",
+ "sha256:39f4b0a6ae22a1c567cb0630c30dd082481f95c13ca528dc501a7766b9c718c0",
+ "sha256:3b0036c978cbcc4a4512278e98e3e6d9e6b834dc973206162eddf98b586ef1c6",
+ "sha256:3ea8c252d8df5e9166bcf3d9edced2af132f4ead8ac422eac723c5781063709a",
+ "sha256:41608c0acbe0899c852281978492f9ce2c6fbfaf60aff0cefc54a7c4516b822c",
+ "sha256:59d11674964b74a81b149d4ceaff2b674b3b0e4d0f10f0be1533e49c4a28408b",
+ "sha256:5e479df4b2d0f8f02133b7e4430098699450e1b2a826438af6bec9a400530957",
+ "sha256:684850fb1e3e55c9220aad007f8386d8e3e477c4ec9211ae54d968ecdca8c6f9",
+ "sha256:6ccc43d68b81c424e46192a778f97da94ee0630337c9bbe5b2ecc9b0c1c59001",
+ "sha256:6d42debaf55450643146fabe4b6817bb2a55b23698b0434107e892a43117285e",
+ "sha256:710376bf67d8ff4500a31d0c207b8941ff4fba5de6890a701d71680474fe2a60",
+ "sha256:756ae7efddd68d4ea7d89c636b703e14a0c686688d42f588b90778a3c2fc0564",
+ "sha256:77149002d9386fae303a4a162e6bce75cc2161347ad2ba06c2f0182561875d45",
+ "sha256:78e2f18a82b88cbc37d22365cf8d2b879a492faedb3f2975adb4ed8dfe994d3a",
+ "sha256:7d9b42127a6c0bdcc25c3dcf252bb3ddc70454fac593b1b6933ae091396deb13",
+ "sha256:8389d6044ee4e2037dca83e3f6994738550f6ee8cfb746762283fad9b932868f",
+ "sha256:9c1a81af067e72261c9cbe33ea792893e83bc6aa987bfbd6fdc1e5e7b22777c4",
+ "sha256:c1e0920909d916d3375c7a1fdb0b1c78e46170e8bb42792312b6eb6676b2f87f",
+ "sha256:c68fdf21c6f3573ae19c7ee65f9ff185649a060c9a06535e9c3a0ee0bbac9235",
+ "sha256:c733ef3bdcfe52a1a75564389bad4064352274036e7e234730526d155f04d914",
+ "sha256:c9c58b0b84055d8bc27b7df5a9d141df4ee6ff59821f922dd73155861282f6a3",
+ "sha256:d03abec50df423b026a5aa09656bd9d37f1e6a49271f123f31f9b8aed5dc3ea3",
+ "sha256:d2cfac21e31e841d60dc28c0ec7d4ec47a35c608cb8906435d47ef83ffb22150",
+ "sha256:dcc119db14757b0c7bce64042158307b9b1c76471e655751a61b57f5a0e4d78e",
+ "sha256:df3a7b258cc230a65245167a202dd07320a5af05f3d41da1488ba0fa05bc9347",
+ "sha256:df48a623c58180874d7407b4d9ec06a19b84ed47f60a3884345b1a5099c1818b",
+ "sha256:e1b95972a0ae3f248a899cdbac92ba2e01d731225f566569311043ce2226f5e7",
+ "sha256:f326b3c1bbfda5b9308252ee0dcb30b612ee92b0e105d4abec70335fab5b1245",
+ "sha256:f411cb22115cb15452d099fec0ee636b06cf81bfb40ed9c02d30c8dc2bc2e3d1"
],
"index": "pypi",
- "version": "==3.6.2"
+ "version": "==3.7.3"
},
"aiohttp-cors": {
"hashes": [
@@ -53,14 +78,16 @@
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
],
+ "markers": "python_full_version >= '3.5.3'",
"version": "==3.0.1"
},
"attrs": {
"hashes": [
- "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
- "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
+ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
+ "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
],
- "version": "==20.2.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==20.3.0"
},
"black": {
"editable": true,
@@ -90,36 +117,60 @@
"sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84"
],
"index": "pypi",
- "version": "==0.6"
+ "python_version <": "3.7",
+ "version": "==0.6",
+ "version >": "0.6"
},
"idna": {
"hashes": [
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.10"
},
"multidict": {
"hashes": [
- "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a",
- "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000",
- "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2",
- "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507",
- "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5",
- "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7",
- "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d",
- "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463",
- "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19",
- "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3",
- "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b",
- "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c",
- "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87",
- "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7",
- "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430",
- "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
- "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
- ],
- "version": "==4.7.6"
+ "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a",
+ "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93",
+ "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632",
+ "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656",
+ "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79",
+ "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7",
+ "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d",
+ "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5",
+ "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224",
+ "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26",
+ "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea",
+ "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348",
+ "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6",
+ "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76",
+ "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1",
+ "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f",
+ "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952",
+ "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a",
+ "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37",
+ "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9",
+ "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359",
+ "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8",
+ "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da",
+ "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3",
+ "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d",
+ "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf",
+ "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841",
+ "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d",
+ "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93",
+ "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f",
+ "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647",
+ "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635",
+ "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456",
+ "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda",
+ "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5",
+ "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281",
+ "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==5.1.0"
},
"mypy-extensions": {
"hashes": [
@@ -131,46 +182,80 @@
},
"pathspec": {
"hashes": [
- "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0",
- "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"
+ "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd",
+ "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"
],
"index": "pypi",
- "version": "==0.8.0"
+ "version": "==0.8.1"
},
"regex": {
"hashes": [
- "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204",
- "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162",
- "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f",
- "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb",
- "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6",
- "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7",
- "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88",
- "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99",
- "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644",
- "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a",
- "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840",
- "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067",
- "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd",
- "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4",
- "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e",
- "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89",
- "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e",
- "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc",
- "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf",
- "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341",
- "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"
+ "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538",
+ "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4",
+ "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc",
+ "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa",
+ "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444",
+ "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1",
+ "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af",
+ "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8",
+ "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9",
+ "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88",
+ "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba",
+ "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364",
+ "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e",
+ "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7",
+ "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0",
+ "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31",
+ "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683",
+ "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee",
+ "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b",
+ "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884",
+ "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c",
+ "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e",
+ "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562",
+ "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85",
+ "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c",
+ "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6",
+ "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d",
+ "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b",
+ "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70",
+ "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b",
+ "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b",
+ "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f",
+ "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0",
+ "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5",
+ "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5",
+ "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f",
+ "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e",
+ "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512",
+ "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d",
+ "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917",
+ "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"
],
"index": "pypi",
- "version": "==2020.7.14"
+ "version": "==2020.11.13"
+ },
+ "setuptools-scm": {
+ "hashes": [
+ "sha256:1fc4e25df445351d172bb4788f4d07f9e9ce0e8b7dee6b19584e46110172ca13",
+ "sha256:48b31488d089270500f120efea723968c01abd85fd4876043a3b7c7ef7d0b761",
+ "sha256:62fa535edb31ece9fa65dc9dcb3056145b8020c8c26c0ef1018aef33db95c40d",
+ "sha256:b928021c4381f96d577847d540d6e03065f8f8851c768a0c9bc552d463bae0d4",
+ "sha256:c85b6b46d0edd40d2301038cdea96bb6adc14d62ef943e75afb08b3e7bcf142a",
+ "sha256:db4ab2e0c2644ba71b1e5212b14ff65dbf0af465796d314a75e0cf6128f605f7",
+ "sha256:e878036c2527dfd05818727846338be86b2be6955741b85fab2625f63d001021",
+ "sha256:eb19b46816fc106a4c2d4180022687eab40f9773cf61390b845afb093d1f4ecd"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==5.0.1"
},
"toml": {
"hashes": [
- "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
+ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+ "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"index": "pypi",
- "version": "==0.10.1"
+ "version": "==0.10.2"
},
"typed-ast": {
"hashes": [
@@ -187,6 +272,7 @@
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
@@ -198,8 +284,10 @@
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
+ "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
"sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"index": "pypi",
@@ -216,61 +304,91 @@
},
"yarl": {
"hashes": [
- "sha256:03b7a44384ad60be1b7be93c2a24dc74895f8d767ea0bce15b2f6fc7695a3843",
- "sha256:076157404db9db4bb3fa9db22db319bbb36d075eeab19ba018ce20ae0cacf037",
- "sha256:1c05ae3d5ea4287470046a2c2754f0a4c171b84ea72c8a691f776eb1753dfb91",
- "sha256:2467baf8233f7c64048df37e11879c553943ffe7f373e689711ec2807ea13805",
- "sha256:2bb2e21cf062dfbe985c3cd4618bae9f25271efcad9e7be1277861247eee9839",
- "sha256:311effab3b3828ab34f0e661bb57ff422f67d5c33056298bda4c12195251f8dd",
- "sha256:3526cb5905907f0e42bee7ef57ae4a5f02bc27dcac27859269e2bba0caa4c2b6",
- "sha256:39b1e586f34b1d2512c9b39aa3cf24c870c972d525e36edc9ee19065db4737bb",
- "sha256:4bed5cd7c8e69551eb19df15295ba90e62b9a6a1149c76eb4a9bab194402a156",
- "sha256:51c6d3cf7a1f1fbe134bb92f33b7affd94d6de24cd64b466eb12de52120fb8c6",
- "sha256:59f78b5da34ddcffb663b772f7619e296518712e022e57fc5d9f921818e2ab7c",
- "sha256:6f29115b0c330da25a04f48612d75333bca04521181a666ca0b8761005a99150",
- "sha256:73d4e1e1ef5e52d526c92f07d16329e1678612c6a81dd8101fdcae11a72de15c",
- "sha256:9b48d31f8d881713fd461abfe7acbb4dcfeb47cec3056aa83f2fbcd2244577f7",
- "sha256:a1fd575dd058e10ad4c35065e7c3007cc74d142f622b14e168d8a273a2fa8713",
- "sha256:b3dd1052afd436ba737e61f5d3bed1f43a7f9a33fc58fbe4226eb919a7006019",
- "sha256:b99c25ed5c355b35d1e6dae87ac7297a4844a57dc5766b173b88b6163a36eb0d",
- "sha256:c056e86bff5a0b566e0d9fab4f67e83b12ae9cbcd250d334cbe2005bbe8c96f2",
- "sha256:c45b49b59a5724869899798e1bbd447ac486215269511d3b76b4c235a1b766b6",
- "sha256:cd623170c729a865037828e3f99f8ebdb22a467177a539680dfc5670b74c84e2",
- "sha256:d25d3311794e6c71b608d7c47651c8f65eea5ab15358a27f29330b3475e8f8e5",
- "sha256:d695439c201ed340745250f9eb4dfe8d32bf1e680c16477107b8f3ce4bff4fdb",
- "sha256:d77f6c9133d2aabb290a7846aaa74ec14d7b5ab35b01591fac5a70c4a8c959a2",
- "sha256:d894a2442d2cd20a3b0b0dce5a353d316c57d25a2b445e03f7eac90eee27b8af",
- "sha256:db643ce2b58a4bd11a82348225c53c76ecdd82bb37cf4c085e6df1b676f4038c",
- "sha256:e3a0c43a26dfed955b2a06fdc4d51d2c51bc2200aff8ce8faf14e676ea8c8862",
- "sha256:e77bf79ad1ccae672eab22453838382fe9029fc27c8029e84913855512a587d8",
- "sha256:f2f0174cb15435957d3b751093f89aede77df59a499ab7516bbb633b77ead13a",
- "sha256:f3031c78edf10315abe232254e6a36b65afe65fded41ee54ed7976d0b2cdf0da",
- "sha256:f4c007156732866aa4507d619fe6f8f2748caabed4f66b276ccd97c82572620c",
- "sha256:f4f27ff3dd80bc7c402def211a47291ea123d59a23f59fe18fc0e81e3e71f385",
- "sha256:f57744fc61e118b5d114ae8077d8eb9df4d2d2c11e2af194e21f0c11ed9dcf6c",
- "sha256:f835015a825980b65356e9520979a1564c56efea7da7d4b68a14d4a07a3a7336"
- ],
- "version": "==1.6.2"
+ "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e",
+ "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434",
+ "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366",
+ "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3",
+ "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec",
+ "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959",
+ "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e",
+ "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c",
+ "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6",
+ "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a",
+ "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6",
+ "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424",
+ "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e",
+ "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f",
+ "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50",
+ "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2",
+ "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc",
+ "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4",
+ "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970",
+ "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10",
+ "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0",
+ "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406",
+ "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896",
+ "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643",
+ "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721",
+ "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478",
+ "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724",
+ "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e",
+ "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8",
+ "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96",
+ "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25",
+ "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76",
+ "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2",
+ "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2",
+ "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c",
+ "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a",
+ "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==1.6.3"
}
},
"develop": {
"aiohttp": {
"hashes": [
- "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e",
- "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326",
- "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a",
- "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654",
- "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a",
- "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4",
- "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17",
- "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec",
- "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd",
- "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48",
- "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59",
- "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"
+ "sha256:0b795072bb1bf87b8620120a6373a3c61bfcb8da7e5c2377f4bb23ff4f0b62c9",
+ "sha256:0d438c8ca703b1b714e82ed5b7a4412c82577040dadff479c08405e2a715564f",
+ "sha256:16a3cb5df5c56f696234ea9e65e227d1ebe9c18aa774d36ff42f532139066a5f",
+ "sha256:1edfd82a98c5161497bbb111b2b70c0813102ad7e0aa81cbeb34e64c93863005",
+ "sha256:2406dc1dda01c7f6060ab586e4601f18affb7a6b965c50a8c90ff07569cf782a",
+ "sha256:2858b2504c8697beb9357be01dc47ef86438cc1cb36ecb6991796d19475faa3e",
+ "sha256:2a7b7640167ab536c3cb90cfc3977c7094f1c5890d7eeede8b273c175c3910fd",
+ "sha256:3228b7a51e3ed533f5472f54f70fd0b0a64c48dc1649a0f0e809bec312934d7a",
+ "sha256:328b552513d4f95b0a2eea4c8573e112866107227661834652a8984766aa7656",
+ "sha256:39f4b0a6ae22a1c567cb0630c30dd082481f95c13ca528dc501a7766b9c718c0",
+ "sha256:3b0036c978cbcc4a4512278e98e3e6d9e6b834dc973206162eddf98b586ef1c6",
+ "sha256:3ea8c252d8df5e9166bcf3d9edced2af132f4ead8ac422eac723c5781063709a",
+ "sha256:41608c0acbe0899c852281978492f9ce2c6fbfaf60aff0cefc54a7c4516b822c",
+ "sha256:59d11674964b74a81b149d4ceaff2b674b3b0e4d0f10f0be1533e49c4a28408b",
+ "sha256:5e479df4b2d0f8f02133b7e4430098699450e1b2a826438af6bec9a400530957",
+ "sha256:684850fb1e3e55c9220aad007f8386d8e3e477c4ec9211ae54d968ecdca8c6f9",
+ "sha256:6ccc43d68b81c424e46192a778f97da94ee0630337c9bbe5b2ecc9b0c1c59001",
+ "sha256:6d42debaf55450643146fabe4b6817bb2a55b23698b0434107e892a43117285e",
+ "sha256:710376bf67d8ff4500a31d0c207b8941ff4fba5de6890a701d71680474fe2a60",
+ "sha256:756ae7efddd68d4ea7d89c636b703e14a0c686688d42f588b90778a3c2fc0564",
+ "sha256:77149002d9386fae303a4a162e6bce75cc2161347ad2ba06c2f0182561875d45",
+ "sha256:78e2f18a82b88cbc37d22365cf8d2b879a492faedb3f2975adb4ed8dfe994d3a",
+ "sha256:7d9b42127a6c0bdcc25c3dcf252bb3ddc70454fac593b1b6933ae091396deb13",
+ "sha256:8389d6044ee4e2037dca83e3f6994738550f6ee8cfb746762283fad9b932868f",
+ "sha256:9c1a81af067e72261c9cbe33ea792893e83bc6aa987bfbd6fdc1e5e7b22777c4",
+ "sha256:c1e0920909d916d3375c7a1fdb0b1c78e46170e8bb42792312b6eb6676b2f87f",
+ "sha256:c68fdf21c6f3573ae19c7ee65f9ff185649a060c9a06535e9c3a0ee0bbac9235",
+ "sha256:c733ef3bdcfe52a1a75564389bad4064352274036e7e234730526d155f04d914",
+ "sha256:c9c58b0b84055d8bc27b7df5a9d141df4ee6ff59821f922dd73155861282f6a3",
+ "sha256:d03abec50df423b026a5aa09656bd9d37f1e6a49271f123f31f9b8aed5dc3ea3",
+ "sha256:d2cfac21e31e841d60dc28c0ec7d4ec47a35c608cb8906435d47ef83ffb22150",
+ "sha256:dcc119db14757b0c7bce64042158307b9b1c76471e655751a61b57f5a0e4d78e",
+ "sha256:df3a7b258cc230a65245167a202dd07320a5af05f3d41da1488ba0fa05bc9347",
+ "sha256:df48a623c58180874d7407b4d9ec06a19b84ed47f60a3884345b1a5099c1818b",
+ "sha256:e1b95972a0ae3f248a899cdbac92ba2e01d731225f566569311043ce2226f5e7",
+ "sha256:f326b3c1bbfda5b9308252ee0dcb30b612ee92b0e105d4abec70335fab5b1245",
+ "sha256:f411cb22115cb15452d099fec0ee636b06cf81bfb40ed9c02d30c8dc2bc2e3d1"
],
"index": "pypi",
- "version": "==3.6.2"
+ "version": "==3.7.3"
},
"aiohttp-cors": {
"hashes": [
@@ -300,21 +418,24 @@
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
"sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
],
+ "markers": "python_full_version >= '3.5.3'",
"version": "==3.0.1"
},
"attrs": {
"hashes": [
- "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
- "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
+ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
+ "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
],
- "version": "==20.2.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==20.3.0"
},
"babel": {
"hashes": [
- "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
- "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
+ "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
+ "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"
],
- "version": "==2.8.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.9.0"
},
"black": {
"editable": true,
@@ -328,61 +449,22 @@
"sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080",
"sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==3.2.1"
},
"certifi": {
"hashes": [
- "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
- "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
- ],
- "version": "==2020.6.20"
- },
- "cffi": {
- "hashes": [
- "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d",
- "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b",
- "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4",
- "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f",
- "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3",
- "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579",
- "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537",
- "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e",
- "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05",
- "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171",
- "sha256:33c6cdc071ba5cd6d96769c8969a0531be2d08c2628a0143a10a7dcffa9719ca",
- "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522",
- "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c",
- "sha256:3eeeb0405fd145e714f7633a5173318bd88d8bbfc3dd0a5751f8c4f70ae629bc",
- "sha256:44f60519595eaca110f248e5017363d751b12782a6f2bd6a7041cba275215f5d",
- "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808",
- "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828",
- "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869",
- "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d",
- "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9",
- "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0",
- "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc",
- "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15",
- "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c",
- "sha256:c11579638288e53fc94ad60022ff1b67865363e730ee41ad5e6f0a17188b327a",
- "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3",
- "sha256:c53af463f4a40de78c58b8b2710ade243c81cbca641e34debf3396a9640d6ec1",
- "sha256:cb763ceceae04803adcc4e2d80d611ef201c73da32d8f2722e9d0ab0c7f10768",
- "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d",
- "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b",
- "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e",
- "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d",
- "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730",
- "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394",
- "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1",
- "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591"
- ],
- "version": "==1.14.3"
+ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
+ "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
+ ],
+ "version": "==2020.12.5"
},
"cfgv": {
"hashes": [
"sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d",
"sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"
],
+ "markers": "python_full_version >= '3.6.1'",
"version": "==3.2.0"
},
"chardet": {
@@ -405,6 +487,7 @@
"sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
"sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==0.4.4"
},
"commonmark": {
@@ -454,34 +537,6 @@
"index": "pypi",
"version": "==5.3"
},
- "cryptography": {
- "hashes": [
- "sha256:22f8251f68953553af4f9c11ec5f191198bc96cff9f0ac5dd5ff94daede0ee6d",
- "sha256:284e275e3c099a80831f9898fb5c9559120d27675c3521278faba54e584a7832",
- "sha256:3e17d02941c0f169c5b877597ca8be895fca0e5e3eb882526a74aa4804380a98",
- "sha256:52a47e60953679eea0b4d490ca3c241fb1b166a7b161847ef4667dfd49e7699d",
- "sha256:57b8c1ed13b8aa386cabbfde3be175d7b155682470b0e259fecfe53850967f8a",
- "sha256:6a8f64ed096d13f92d1f601a92d9fd1f1025dc73a2ca1ced46dcf5e0d4930943",
- "sha256:6e8a3c7c45101a7eeee93102500e1b08f2307c717ff553fcb3c1127efc9b6917",
- "sha256:7ef41304bf978f33cfb6f43ca13bb0faac0c99cda33693aa20ad4f5e34e8cb8f",
- "sha256:87c2fffd61e934bc0e2c927c3764c20b22d7f5f7f812ee1a477de4c89b044ca6",
- "sha256:88069392cd9a1e68d2cfd5c3a2b0d72a44ef3b24b8977a4f7956e9e3c4c9477a",
- "sha256:8a0866891326d3badb17c5fd3e02c926b635e8923fa271b4813cd4d972a57ff3",
- "sha256:8f0fd8b0751d75c4483c534b209e39e918f0d14232c0d8a2a76e687f64ced831",
- "sha256:9a07e6d255053674506091d63ab4270a119e9fc83462c7ab1dbcb495b76307af",
- "sha256:9a8580c9afcdcddabbd064c0a74f337af74ff4529cdf3a12fa2e9782d677a2e5",
- "sha256:bd80bc156d3729b38cb227a5a76532aef693b7ac9e395eea8063ee50ceed46a5",
- "sha256:d1cbc3426e6150583b22b517ef3720036d7e3152d428c864ff0f3fcad2b97591",
- "sha256:e15ac84dcdb89f92424cbaca4b0b34e211e7ce3ee7b0ec0e4f3c55cee65fae5a",
- "sha256:e4789b84f8dedf190148441f7c5bfe7244782d9cbb194a36e17b91e7d3e1cca9",
- "sha256:f01c9116bfb3ad2831e125a73dcd957d173d6ddca7701528eff1e7d97972872c",
- "sha256:f0e3986f6cce007216b23c490f093f35ce2068f3c244051e559f647f6731b7ae",
- "sha256:f2aa3f8ba9e2e3fd49bd3de743b976ab192fbf0eb0348cebde5d2a9de0090a9f",
- "sha256:fb70a4cedd69dc52396ee114416a3656e011fb0311fca55eb55c7be6ed9c8aef"
- ],
- "index": "pypi",
- "version": "==3.2"
- },
"distlib": {
"hashes": [
"sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb",
@@ -492,6 +547,7 @@
"docutils": {
"hashes": [
"sha256:54a349c622ff31c91cbec43b0b512f113b5b24daf00e2ea530bb1bd9aac14849",
+ "sha256:ba4584f9107571ced0d2c7f56a5499c696215ba90797849c92d395979da68521",
"sha256:d2ddba74835cb090a1b627d3de4e7835c628d07ee461f7b4480f51af2fe4d448"
],
"index": "pypi",
@@ -506,40 +562,34 @@
},
"flake8": {
"hashes": [
- "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c",
- "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"
+ "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839",
+ "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"
],
"index": "pypi",
- "version": "==3.8.3"
+ "version": "==3.8.4"
},
"flake8-bugbear": {
"hashes": [
- "sha256:a3ddc03ec28ba2296fc6f89444d1c946a6b76460f859795b35b77d4920a51b63",
- "sha256:bd02e4b009fb153fe6072c31c52aeab5b133d508095befb2ffcf3b41c4823162"
- ],
- "index": "pypi",
- "version": "==20.1.4"
- },
- "flake8-mypy": {
- "hashes": [
- "sha256:47120db63aff631ee1f84bac6fe8e64731dc66da3efc1c51f85e15ade4a3ba18",
- "sha256:cff009f4250e8391bf48990093cff85802778c345c8449d6498b62efefeebcbc"
+ "sha256:528020129fea2dea33a466b9d64ab650aa3e5f9ffc788b70ea4bc6cf18283538",
+ "sha256:f35b8135ece7a014bc0aee5b5d485334ac30a6da48494998cc1fabf7ec70d703"
],
"index": "pypi",
- "version": "==17.8.0"
+ "version": "==20.11.1"
},
"identify": {
"hashes": [
- "sha256:3139bf72d81dfd785b0a464e2776bd59bdc725b4cc10e6cf46b56a0db931c82e",
- "sha256:969d844b7a85d32a5f9ac4e163df6e846d73c87c8b75847494ee8f4bd2186421"
+ "sha256:943cd299ac7f5715fcb3f684e2fc1594c1e0f22a90d15398e5888143bd4144b5",
+ "sha256:cc86e6a9a390879dcc2976cef169dd9cc48843ed70b7380f321d1b118163c60e"
],
- "version": "==1.5.6"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.5.10"
},
"idna": {
"hashes": [
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.10"
},
"imagesize": {
@@ -547,29 +597,24 @@
"sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1",
"sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.2.0"
},
- "jeepney": {
- "hashes": [
- "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e",
- "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf"
- ],
- "markers": "sys_platform == 'linux'",
- "version": "==0.4.3"
- },
"jinja2": {
"hashes": [
"sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0",
"sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==2.11.2"
},
"keyring": {
"hashes": [
- "sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d",
- "sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466"
+ "sha256:12de23258a95f3b13e5b167f7a641a878e91eab8ef16fafc077720a95e6115bb",
+ "sha256:207bd66f2a9881c835dad653da04e196c678bf104f8252141d2d3c4f31051579"
],
- "version": "==21.4.0"
+ "markers": "python_version >= '3.6'",
+ "version": "==21.5.0"
},
"markupsafe": {
"hashes": [
@@ -607,6 +652,7 @@
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.1.1"
},
"mccabe": {
@@ -618,45 +664,66 @@
},
"multidict": {
"hashes": [
- "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a",
- "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000",
- "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2",
- "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507",
- "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5",
- "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7",
- "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d",
- "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463",
- "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19",
- "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3",
- "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b",
- "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c",
- "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87",
- "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7",
- "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430",
- "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
- "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
- ],
- "version": "==4.7.6"
+ "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a",
+ "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93",
+ "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632",
+ "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656",
+ "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79",
+ "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7",
+ "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d",
+ "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5",
+ "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224",
+ "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26",
+ "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea",
+ "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348",
+ "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6",
+ "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76",
+ "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1",
+ "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f",
+ "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952",
+ "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a",
+ "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37",
+ "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9",
+ "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359",
+ "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8",
+ "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da",
+ "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3",
+ "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d",
+ "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf",
+ "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841",
+ "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d",
+ "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93",
+ "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f",
+ "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647",
+ "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635",
+ "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456",
+ "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda",
+ "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5",
+ "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281",
+ "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==5.1.0"
},
"mypy": {
"hashes": [
- "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c",
- "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86",
- "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b",
- "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd",
- "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc",
- "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea",
- "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e",
- "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308",
- "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406",
- "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d",
- "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707",
- "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d",
- "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c",
- "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"
+ "sha256:0a0d102247c16ce93c97066443d11e2d36e6cc2a32d8ccc1f705268970479324",
+ "sha256:0d34d6b122597d48a36d6c59e35341f410d4abfa771d96d04ae2c468dd201abc",
+ "sha256:2170492030f6faa537647d29945786d297e4862765f0b4ac5930ff62e300d802",
+ "sha256:2842d4fbd1b12ab422346376aad03ff5d0805b706102e475e962370f874a5122",
+ "sha256:2b21ba45ad9ef2e2eb88ce4aeadd0112d0f5026418324176fd494a6824b74975",
+ "sha256:72060bf64f290fb629bd4a67c707a66fd88ca26e413a91384b18db3876e57ed7",
+ "sha256:af4e9ff1834e565f1baa74ccf7ae2564ae38c8df2a85b057af1dbbc958eb6666",
+ "sha256:bd03b3cf666bff8d710d633d1c56ab7facbdc204d567715cb3b9f85c6e94f669",
+ "sha256:c614194e01c85bb2e551c421397e49afb2872c88b5830e3554f0519f9fb1c178",
+ "sha256:cf4e7bf7f1214826cf7333627cb2547c0db7e3078723227820d0a2490f117a01",
+ "sha256:da56dedcd7cd502ccd3c5dddc656cb36113dd793ad466e894574125945653cea",
+ "sha256:e86bdace26c5fe9cf8cb735e7cedfe7850ad92b327ac5d797c656717d2ca66de",
+ "sha256:e97e9c13d67fbe524be17e4d8025d51a7dca38f90de2e462243ab8ed8a9178d1",
+ "sha256:eea260feb1830a627fb526d22fbb426b750d9f5a47b624e8d5e7e004359b219c"
],
"index": "pypi",
- "version": "==0.782"
+ "version": "==0.790"
},
"mypy-extensions": {
"hashes": [
@@ -675,18 +742,19 @@
},
"packaging": {
"hashes": [
- "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
- "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
+ "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
+ "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"
],
- "version": "==20.4"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==20.8"
},
"pathspec": {
"hashes": [
- "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0",
- "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"
+ "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd",
+ "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"
],
"index": "pypi",
- "version": "==0.8.0"
+ "version": "==0.8.1"
},
"pkginfo": {
"hashes": [
@@ -697,64 +765,63 @@
},
"pre-commit": {
"hashes": [
- "sha256:810aef2a2ba4f31eed1941fc270e72696a1ad5590b9751839c90807d0fff6b9a",
- "sha256:c54fd3e574565fe128ecc5e7d2f91279772ddb03f8729645fa812fe809084a70"
+ "sha256:6c86d977d00ddc8a60d68eec19f51ef212d9462937acf3ea37c7adec32284ac0",
+ "sha256:ee784c11953e6d8badb97d19bc46b997a3a9eded849881ec587accd8608d74a4"
],
"index": "pypi",
- "version": "==2.7.1"
+ "version": "==2.9.3"
},
"pycodestyle": {
"hashes": [
"sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
"sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.6.0"
},
- "pycparser": {
- "hashes": [
- "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
- "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
- ],
- "version": "==2.20"
- },
"pyflakes": {
"hashes": [
"sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
"sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.2.0"
},
"pygments": {
"hashes": [
- "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0",
- "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"
+ "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716",
+ "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"
],
- "version": "==2.7.2"
+ "markers": "python_version >= '3.5'",
+ "version": "==2.7.3"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.4.7"
},
"pytz": {
"hashes": [
- "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
- "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"
+ "sha256:3e6b7dd2d1e0a59084bcee14a17af60c5c562cdc16d828e8eba2e683d3a7e268",
+ "sha256:5c55e189b682d420be27c6995ba6edce0c0a77dd67bfbe2ae6607134d5851ffd"
],
- "version": "==2020.1"
+ "version": "==2020.4"
},
"pyyaml": {
"hashes": [
"sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
"sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
"sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
+ "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e",
"sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
"sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
"sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
"sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
"sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
+ "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a",
"sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
"sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
"sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
@@ -763,11 +830,11 @@
},
"readme-renderer": {
"hashes": [
- "sha256:cbe9db71defedd2428a1589cdc545f9bd98e59297449f69d721ef8f1cfced68d",
- "sha256:cc4957a803106e820d05d14f71033092537a22daa4f406dfbdd61177e0936376"
+ "sha256:267854ac3b1530633c2394ead828afcd060fc273217c42ac36b6be9c42cd9a9d",
+ "sha256:6b7e5aa59210a40de72eb79931491eaf46fefca2952b9181268bd7c7c65c260a"
],
"index": "pypi",
- "version": "==26.0"
+ "version": "==28.0"
},
"recommonmark": {
"hashes": [
@@ -779,37 +846,58 @@
},
"regex": {
"hashes": [
- "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204",
- "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162",
- "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f",
- "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb",
- "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6",
- "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7",
- "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88",
- "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99",
- "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644",
- "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a",
- "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840",
- "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067",
- "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd",
- "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4",
- "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e",
- "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89",
- "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e",
- "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc",
- "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf",
- "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341",
- "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"
+ "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538",
+ "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4",
+ "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc",
+ "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa",
+ "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444",
+ "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1",
+ "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af",
+ "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8",
+ "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9",
+ "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88",
+ "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba",
+ "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364",
+ "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e",
+ "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7",
+ "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0",
+ "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31",
+ "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683",
+ "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee",
+ "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b",
+ "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884",
+ "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c",
+ "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e",
+ "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562",
+ "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85",
+ "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c",
+ "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6",
+ "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d",
+ "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b",
+ "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70",
+ "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b",
+ "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b",
+ "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f",
+ "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0",
+ "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5",
+ "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5",
+ "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f",
+ "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e",
+ "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512",
+ "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d",
+ "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917",
+ "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"
],
"index": "pypi",
- "version": "==2020.7.14"
+ "version": "==2020.11.13"
},
"requests": {
"hashes": [
- "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
- "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
+ "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8",
+ "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"
],
- "version": "==2.24.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==2.25.0"
},
"requests-toolbelt": {
"hashes": [
@@ -825,27 +913,26 @@
],
"version": "==1.4.0"
},
- "secretstorage": {
- "hashes": [
- "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6",
- "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b"
- ],
- "markers": "sys_platform == 'linux'",
- "version": "==3.1.2"
- },
"setuptools-scm": {
"hashes": [
- "sha256:69258e2eeba5f7ce1ed7a5f109519580fa3578250f8e4d6684859f86d1b15826",
- "sha256:a8994582e716ec690f33fec70cca0f85bd23ec974e3f783233e4879090a7faa8"
+ "sha256:1fc4e25df445351d172bb4788f4d07f9e9ce0e8b7dee6b19584e46110172ca13",
+ "sha256:48b31488d089270500f120efea723968c01abd85fd4876043a3b7c7ef7d0b761",
+ "sha256:62fa535edb31ece9fa65dc9dcb3056145b8020c8c26c0ef1018aef33db95c40d",
+ "sha256:b928021c4381f96d577847d540d6e03065f8f8851c768a0c9bc552d463bae0d4",
+ "sha256:c85b6b46d0edd40d2301038cdea96bb6adc14d62ef943e75afb08b3e7bcf142a",
+ "sha256:db4ab2e0c2644ba71b1e5212b14ff65dbf0af465796d314a75e0cf6128f605f7",
+ "sha256:e878036c2527dfd05818727846338be86b2be6955741b85fab2625f63d001021",
+ "sha256:eb19b46816fc106a4c2d4180022687eab40f9773cf61390b845afb093d1f4ecd"
],
- "index": "pypi",
- "version": "==4.1.2"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==5.0.1"
},
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.15.0"
},
"snowballstemmer": {
@@ -857,17 +944,18 @@
},
"sphinx": {
"hashes": [
- "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8",
- "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0"
+ "sha256:1e8d592225447104d1172be415bc2972bd1357e3e12fdc76edf2261105db4300",
+ "sha256:d4e59ad4ea55efbb3c05cde3bfc83bfc14f0c95aa95c3d75346fcce186a47960"
],
"index": "pypi",
- "version": "==3.2.1"
+ "version": "==3.3.1"
},
"sphinxcontrib-applehelp": {
"hashes": [
"sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a",
"sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.0.2"
},
"sphinxcontrib-devhelp": {
@@ -875,6 +963,7 @@
"sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e",
"sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.0.2"
},
"sphinxcontrib-htmlhelp": {
@@ -882,6 +971,7 @@
"sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f",
"sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.0.3"
},
"sphinxcontrib-jsmath": {
@@ -889,6 +979,7 @@
"sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
"sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.0.1"
},
"sphinxcontrib-qthelp": {
@@ -896,6 +987,7 @@
"sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72",
"sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.0.3"
},
"sphinxcontrib-serializinghtml": {
@@ -903,22 +995,24 @@
"sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc",
"sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.1.4"
},
"toml": {
"hashes": [
- "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
+ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+ "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"index": "pypi",
- "version": "==0.10.1"
+ "version": "==0.10.2"
},
"tqdm": {
"hashes": [
- "sha256:9ad44aaf0fc3697c06f6e05c7cf025dd66bc7bcb7613c66d85f4464c47ac8fad",
- "sha256:ef54779f1c09f346b2b5a8e5c61f96fbcb639929e640e59f8cf810794f406432"
+ "sha256:38b658a3e4ecf9b4f6f8ff75ca16221ae3378b2e175d846b6b33ea3a20852cf5",
+ "sha256:d4f413aecb61c9779888c64ddf0c62910ad56dcbe857d8922bb505d4dbff0df1"
],
- "version": "==4.51.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==4.54.1"
},
"twine": {
"hashes": [
@@ -943,6 +1037,7 @@
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
@@ -954,8 +1049,10 @@
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
+ "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
"sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"index": "pypi",
@@ -972,17 +1069,19 @@
},
"urllib3": {
"hashes": [
- "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
- "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
+ "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08",
+ "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"
],
- "version": "==1.25.11"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
+ "version": "==1.26.2"
},
"virtualenv": {
"hashes": [
- "sha256:b0011228208944ce71052987437d3843e05690b2f23d1c7da4263fde104c97a2",
- "sha256:b8d6110f493af256a40d65e29846c69340a947669eec8ce784fcf3dd3af28380"
+ "sha256:54b05fc737ea9c9ee9f8340f579e5da5b09fb64fd010ab5757eb90268616907c",
+ "sha256:b7a8ec323ee02fb2312f098b6b4c9de99559b462775bc8fe3627a73706603c1b"
],
- "version": "==20.1.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==20.2.2"
},
"webencodings": {
"hashes": [
@@ -993,49 +1092,54 @@
},
"wheel": {
"hashes": [
- "sha256:497add53525d16c173c2c1c733b8f655510e909ea78cc0e29d374243544b77a2",
- "sha256:99a22d87add3f634ff917310a3d87e499f19e663413a52eb9232c447aa646c9f"
+ "sha256:78b5b185f0e5763c26ca1e324373aadd49182ca90e825f7853f4b2509215dc0e",
+ "sha256:e11eefd162658ea59a60a0f6c7d493a7190ea4b9a85e335b33489d9f17e0245e"
],
"index": "pypi",
- "version": "==0.35.1"
+ "version": "==0.36.2"
},
"yarl": {
"hashes": [
- "sha256:03b7a44384ad60be1b7be93c2a24dc74895f8d767ea0bce15b2f6fc7695a3843",
- "sha256:076157404db9db4bb3fa9db22db319bbb36d075eeab19ba018ce20ae0cacf037",
- "sha256:1c05ae3d5ea4287470046a2c2754f0a4c171b84ea72c8a691f776eb1753dfb91",
- "sha256:2467baf8233f7c64048df37e11879c553943ffe7f373e689711ec2807ea13805",
- "sha256:2bb2e21cf062dfbe985c3cd4618bae9f25271efcad9e7be1277861247eee9839",
- "sha256:311effab3b3828ab34f0e661bb57ff422f67d5c33056298bda4c12195251f8dd",
- "sha256:3526cb5905907f0e42bee7ef57ae4a5f02bc27dcac27859269e2bba0caa4c2b6",
- "sha256:39b1e586f34b1d2512c9b39aa3cf24c870c972d525e36edc9ee19065db4737bb",
- "sha256:4bed5cd7c8e69551eb19df15295ba90e62b9a6a1149c76eb4a9bab194402a156",
- "sha256:51c6d3cf7a1f1fbe134bb92f33b7affd94d6de24cd64b466eb12de52120fb8c6",
- "sha256:59f78b5da34ddcffb663b772f7619e296518712e022e57fc5d9f921818e2ab7c",
- "sha256:6f29115b0c330da25a04f48612d75333bca04521181a666ca0b8761005a99150",
- "sha256:73d4e1e1ef5e52d526c92f07d16329e1678612c6a81dd8101fdcae11a72de15c",
- "sha256:9b48d31f8d881713fd461abfe7acbb4dcfeb47cec3056aa83f2fbcd2244577f7",
- "sha256:a1fd575dd058e10ad4c35065e7c3007cc74d142f622b14e168d8a273a2fa8713",
- "sha256:b3dd1052afd436ba737e61f5d3bed1f43a7f9a33fc58fbe4226eb919a7006019",
- "sha256:b99c25ed5c355b35d1e6dae87ac7297a4844a57dc5766b173b88b6163a36eb0d",
- "sha256:c056e86bff5a0b566e0d9fab4f67e83b12ae9cbcd250d334cbe2005bbe8c96f2",
- "sha256:c45b49b59a5724869899798e1bbd447ac486215269511d3b76b4c235a1b766b6",
- "sha256:cd623170c729a865037828e3f99f8ebdb22a467177a539680dfc5670b74c84e2",
- "sha256:d25d3311794e6c71b608d7c47651c8f65eea5ab15358a27f29330b3475e8f8e5",
- "sha256:d695439c201ed340745250f9eb4dfe8d32bf1e680c16477107b8f3ce4bff4fdb",
- "sha256:d77f6c9133d2aabb290a7846aaa74ec14d7b5ab35b01591fac5a70c4a8c959a2",
- "sha256:d894a2442d2cd20a3b0b0dce5a353d316c57d25a2b445e03f7eac90eee27b8af",
- "sha256:db643ce2b58a4bd11a82348225c53c76ecdd82bb37cf4c085e6df1b676f4038c",
- "sha256:e3a0c43a26dfed955b2a06fdc4d51d2c51bc2200aff8ce8faf14e676ea8c8862",
- "sha256:e77bf79ad1ccae672eab22453838382fe9029fc27c8029e84913855512a587d8",
- "sha256:f2f0174cb15435957d3b751093f89aede77df59a499ab7516bbb633b77ead13a",
- "sha256:f3031c78edf10315abe232254e6a36b65afe65fded41ee54ed7976d0b2cdf0da",
- "sha256:f4c007156732866aa4507d619fe6f8f2748caabed4f66b276ccd97c82572620c",
- "sha256:f4f27ff3dd80bc7c402def211a47291ea123d59a23f59fe18fc0e81e3e71f385",
- "sha256:f57744fc61e118b5d114ae8077d8eb9df4d2d2c11e2af194e21f0c11ed9dcf6c",
- "sha256:f835015a825980b65356e9520979a1564c56efea7da7d4b68a14d4a07a3a7336"
- ],
- "version": "==1.6.2"
+ "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e",
+ "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434",
+ "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366",
+ "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3",
+ "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec",
+ "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959",
+ "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e",
+ "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c",
+ "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6",
+ "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a",
+ "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6",
+ "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424",
+ "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e",
+ "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f",
+ "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50",
+ "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2",
+ "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc",
+ "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4",
+ "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970",
+ "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10",
+ "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0",
+ "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406",
+ "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896",
+ "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643",
+ "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721",
+ "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478",
+ "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724",
+ "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e",
+ "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8",
+ "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96",
+ "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25",
+ "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76",
+ "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2",
+ "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2",
+ "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c",
+ "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a",
+ "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==1.6.3"
}
}
}
diff --git a/mypy.ini b/mypy.ini
index 295bab4e302..589fbf65139 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -5,7 +5,6 @@
python_version=3.6
platform=linux
-# flake8-mypy expects the two following for sensible formatting
show_column_numbers=True
# show error messages from unrelated files
From c3df2c1a69c687d34f41478235c869d0526a46bd Mon Sep 17 00:00:00 2001
From: nikkie
Date: Mon, 28 Dec 2020 00:18:35 +0900
Subject: [PATCH 0053/1034] fix format_str() docstring to prevent users from
running into NameError (#1885)
---
src/black/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 48690573810..5f0f89719f9 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -986,7 +986,7 @@ def format_str(src_contents: str, *, mode: Mode) -> FileContent:
allowed. Example:
>>> import black
- >>> print(black.format_str("def f(arg:str='')->None:...", mode=Mode()))
+ >>> print(black.format_str("def f(arg:str='')->None:...", mode=black.Mode()))
def f(arg: str = "") -> None:
...
From e7ddcb8686859cf3033b2a5d1a2934426abdae9d Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Sun, 27 Dec 2020 10:19:08 -0500
Subject: [PATCH 0054/1034] Fuzz on Python 3.9 too (#1882)
Fuzzing on Python 3.9 used to cause errors but now they have disappeared
on more modern Python 3.9 and Hypothesmith.
---
.github/workflows/fuzz.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 343eed10df8..0153767509a 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [3.6, 3.7, 3.8] # Python3.9 should be added after fixing [https://github.com/Zac-HD/hypothesmith/issues/11].
+ python-version: [3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2
From a497570fcb364b40e0d952d3133e8d4f2d329fea Mon Sep 17 00:00:00 2001
From: Richard Si <63936253+ichard26@users.noreply.github.com>
Date: Sun, 27 Dec 2020 21:38:11 -0500
Subject: [PATCH 0055/1034] Bump mypy to 0.780 in pre-commit config (#1887)
To avoid hitting a mypy bug causes pre-commit to always fail on CPython
3.9. Even though it's still an outdated version, the bug effectively
blocks development on CPython 3.9 so that's why this commit exists
instead of waiting for cooperlees to finish his bump to 0.790 PR.
Also this fixes primer to ensure it always raises CalledProcessError
with an int error code. I stole the patch from cooperlees's mypy bump
PR.
It's funny how mypy 0.790 is already asked for in our
Pipfile.lock file, but oh well mypy is probably more commonly run
through pre-commit than standalone I guess.
Oh and if you're curious why the bug doesn't up on CPython 3.8 or lower:
there was some subscription AST changes in CPython 3.9.
---
.pre-commit-config.yaml | 2 +-
src/black_primer/lib.py | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 667b22d6328..4e12e46f8d8 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -18,7 +18,7 @@ repos:
additional_dependencies: [flake8-bugbear]
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v0.770
+ rev: v0.780
hooks:
- id: mypy
exclude: ^docs/conf.py
diff --git a/src/black_primer/lib.py b/src/black_primer/lib.py
index afeb0721cc4..5c5576e1ff3 100644
--- a/src/black_primer/lib.py
+++ b/src/black_primer/lib.py
@@ -59,10 +59,12 @@ async def _gen_check_output(
raise
if process.returncode != 0:
+ returncode = process.returncode
+ if returncode is None:
+ returncode = 69
+
cmd_str = " ".join(cmd)
- raise CalledProcessError(
- process.returncode, cmd_str, output=stdout, stderr=stderr
- )
+ raise CalledProcessError(returncode, cmd_str, output=stdout, stderr=stderr)
return (stdout, stderr)
From e912c7ff54c392e92a765c5eff0bd2ca3bb05b47 Mon Sep 17 00:00:00 2001
From: Bryan Bugyi
Date: Mon, 28 Dec 2020 15:30:23 -0500
Subject: [PATCH 0056/1034] Fix INTERNAL ERROR caused by removing parens from
pointless string (#1888)
Fixes #1846.
---
src/black/__init__.py | 11 ++++++-
tests/data/long_strings__regression.py | 42 ++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/src/black/__init__.py b/src/black/__init__.py
index 5f0f89719f9..c7c5d724a9f 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -3271,7 +3271,8 @@ class StringParenStripper(StringTransformer):
Requirements:
The line contains a string which is surrounded by parentheses and:
- - The target string is NOT the only argument to a function call).
+ - The target string is NOT the only argument to a function call.
+ - The target string is NOT a "pointless" string.
- If the target string contains a PERCENT, the brackets are not
preceeded or followed by an operator with higher precedence than
PERCENT.
@@ -3295,6 +3296,14 @@ def do_match(self, line: Line) -> TMatchResult:
if leaf.type != token.STRING:
continue
+ # If this is a "pointless" string...
+ if (
+ leaf.parent
+ and leaf.parent.parent
+ and leaf.parent.parent.type == syms.simple_stmt
+ ):
+ continue
+
# Should be preceded by a non-empty LPAR...
if (
not is_valid_index(idx - 1)
diff --git a/tests/data/long_strings__regression.py b/tests/data/long_strings__regression.py
index 7065b2fcef8..2e7f2483b63 100644
--- a/tests/data/long_strings__regression.py
+++ b/tests/data/long_strings__regression.py
@@ -375,6 +375,27 @@ def xxxxxxx_xxxxxx(xxxx):
print(f"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam. {[f'{i}' for i in range(10)]}")
x = f"This is a long string which contains an f-expr that should not split {{{[i for i in range(5)]}}}."
+# The parens should NOT be removed in this case.
+(
+ "my very long string that should get formatted if I'm careful to make sure it goes"
+ " over 88 characters which it has now"
+)
+
+# The parens should NOT be removed in this case.
+(
+ "my very long string that should get formatted if I'm careful to make sure it goes over 88 characters which"
+ " it has now"
+)
+
+# The parens should NOT be removed in this case.
+(
+ "my very long string"
+ " that should get formatted"
+ " if I'm careful to make sure"
+ " it goes over 88 characters which"
+ " it has now"
+)
+
# output
@@ -844,3 +865,24 @@ def xxxxxxx_xxxxxx(xxxx):
"This is a long string which contains an f-expr that should not split"
f" {{{[i for i in range(5)]}}}."
)
+
+# The parens should NOT be removed in this case.
+(
+ "my very long string that should get formatted if I'm careful to make sure it goes"
+ " over 88 characters which it has now"
+)
+
+# The parens should NOT be removed in this case.
+(
+ "my very long string that should get formatted if I'm careful to make sure it goes"
+ " over 88 characters which it has now"
+)
+
+# The parens should NOT be removed in this case.
+(
+ "my very long string"
+ " that should get formatted"
+ " if I'm careful to make sure"
+ " it goes over 88 characters which"
+ " it has now"
+)
From d34eb7fea38384cd1cd029179298116fabdbccd4 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade
Date: Thu, 31 Dec 2020 19:03:39 +0200
Subject: [PATCH 0057/1034] As long as it's black (#1893)
Make background transparent for dark mode
---
docs/_static/logo2-readme.png | Bin 80754 -> 99591 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/docs/_static/logo2-readme.png b/docs/_static/logo2-readme.png
index ec5dafb64958d222ecbe9a29e9e13963acc6d73d..7704ec01ed98a803f59465020422ff6cd24c0958 100644
GIT binary patch
literal 99591
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 |