Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch from attrs to dataclasses #1116

Merged
merged 3 commits into from Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Pipfile
Expand Up @@ -5,7 +5,6 @@ name = "pypi"

[packages]
aiohttp = ">=3.3.2"
attrs = ">=18.1.0"
click = ">=6.5"
appdirs = "*"
toml = ">=0.9.4"
Expand All @@ -14,6 +13,7 @@ aiohttp-cors = "*"
typed-ast = "==1.4.0"
regex = ">=2019.8"
pathspec = ">=0.6"
dataclasses = {version = ">=0.6", python_version = "< 3.7"}

[dev-packages]
pre-commit = "*"
Expand Down
10 changes: 9 additions & 1 deletion Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 16 additions & 14 deletions black.py
Expand Up @@ -39,7 +39,7 @@
)

from appdirs import user_cache_dir
from attr import dataclass, evolve, Factory
from dataclasses import dataclass, field
import click
import toml
from typed_ast import ast3, ast27
Expand Down Expand Up @@ -185,7 +185,7 @@ class Feature(Enum):

@dataclass
class FileMode:
target_versions: Set[TargetVersion] = Factory(set)
target_versions: Set[TargetVersion] = field(default_factory=set)
line_length: int = DEFAULT_LINE_LENGTH
string_normalization: bool = True
is_pyi: bool = False
Expand Down Expand Up @@ -629,7 +629,7 @@ def format_file_in_place(
`mode` and `fast` options are passed to :func:`format_file_contents`.
"""
if src.suffix == ".pyi":
mode = evolve(mode, is_pyi=True)
mode = mode.replace(is_pyi=True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's actually dataclasses.replace, a global function (presumably so dataclasses don't inject a .replace method everywhere)


then = datetime.utcfromtimestamp(src.stat().st_mtime)
with open(src, "rb") as buf:
Expand Down Expand Up @@ -1028,11 +1028,11 @@ class BracketTracker:
"""Keeps track of brackets on a line."""

depth: int = 0
bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = Factory(dict)
delimiters: Dict[LeafID, Priority] = Factory(dict)
bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = field(default_factory=dict)
delimiters: Dict[LeafID, Priority] = field(default_factory=dict)
previous: Optional[Leaf] = None
_for_loop_depths: List[int] = Factory(list)
_lambda_argument_depths: List[int] = Factory(list)
_for_loop_depths: List[int] = field(default_factory=list)
_lambda_argument_depths: List[int] = field(default_factory=list)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it makes sense to define a helper:

def Factory(fn):
    return field(default_factory=fn)

to minimize the size of the diff? Not sure however what looks better.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code is fine. I'd rather use dataclasses idiomatically than minimize diff size.


def mark(self, leaf: Leaf) -> None:
"""Mark `leaf` with bracket-related metadata. Keep track of delimiters.
Expand Down Expand Up @@ -1160,9 +1160,11 @@ class Line:
"""Holds leaves and comments. Can be printed with `str(line)`."""

depth: int = 0
leaves: List[Leaf] = Factory(list)
comments: Dict[LeafID, List[Leaf]] = Factory(dict) # keys ordered like `leaves`
bracket_tracker: BracketTracker = Factory(BracketTracker)
leaves: List[Leaf] = field(default_factory=list)
comments: Dict[LeafID, List[Leaf]] = field(
default_factory=dict
) # keys ordered like `leaves`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put this comment on the previous line by itself instead? (I'd personally prefer if Black did that automatically in this case.)

bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
inside_brackets: bool = False
should_explode: bool = False

Expand Down Expand Up @@ -1565,7 +1567,7 @@ class EmptyLineTracker:
is_pyi: bool = False
previous_line: Optional[Line] = None
previous_after: int = 0
previous_defs: List[int] = Factory(list)
previous_defs: List[int] = field(default_factory=list)

def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
"""Return the number of extra empty lines before and after the `current_line`.
Expand Down Expand Up @@ -1679,7 +1681,7 @@ class LineGenerator(Visitor[Line]):

is_pyi: bool = False
normalize_strings: bool = True
current_line: Line = Factory(Line)
current_line: Line = field(default_factory=Line)
remove_u_prefix: bool = False

def line(self, indent: int = 0) -> Iterator[Line]:
Expand Down Expand Up @@ -1844,7 +1846,7 @@ def visit_factor(self, node: Node) -> Iterator[Line]:
node.insert_child(index, Node(syms.atom, [lpar, operand, rpar]))
yield from self.visit_default(node)

def __attrs_post_init__(self) -> None:
def __post_init__(self) -> None:
"""You are in a twisty little maze of passages."""
v = self.visit_stmt
Ø: Set[str] = set()
Expand Down Expand Up @@ -3712,7 +3714,7 @@ def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[st

yield f"{' ' * depth}{node.__class__.__name__}("

for field in sorted(node._fields):
for field in sorted(node._fields): # noqa: F402
# TypeIgnore has only one field 'lineno' which breaks this comparison
type_ignore_classes = (ast3.TypeIgnore, ast27.TypeIgnore)
if sys.version_info >= (3, 8):
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -42,7 +42,8 @@ def get_long_description() -> str:
"typed-ast>=1.4.0",
"regex",
"pathspec>=0.6, <1",
],
]
+ (["dataclasses>=0.6"] if sys.version_info < (3, 7) else []),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to do it like in python/typing@f254d69

extras_require={"d": ["aiohttp>=3.3.2", "aiohttp-cors"]},
test_suite="tests.test_black",
classifiers=[
Expand Down