mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-20 21:14:14 +08:00
Add ufmt to unify black and usort (#81157)
This reworks [80257](https://github.com/pytorch/pytorch/pull/80257) a bit to use ufmt: * ufmt https://ufmt.omnilib.dev/en/stable/ unifies both black and usort to automatically format the file in the "most Pythonic" way * Also make a demo run for all files in `tools/linter/**/*.py` Pull Request resolved: https://github.com/pytorch/pytorch/pull/81157 Approved by: https://github.com/suo
This commit is contained in:
@ -653,3 +653,31 @@ init_command = [
|
|||||||
'--dry-run={{DRYRUN}}',
|
'--dry-run={{DRYRUN}}',
|
||||||
'PyYAML==6.0',
|
'PyYAML==6.0',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# This also provides the same functionality as BLACK formatter. Just to be
|
||||||
|
# on the safe side, we will run both BLACK and UFMT for a while to make sure
|
||||||
|
# that nothing breaks before removing the former
|
||||||
|
[[linter]]
|
||||||
|
code = 'UFMT'
|
||||||
|
# This is a big bang change to reformat every python files in the repo,
|
||||||
|
# so it's arguably safer to gradually reformat them in subsequent PR.
|
||||||
|
# After that, we can use **/*.py to apply the formatter to everything
|
||||||
|
include_patterns = ['tools/linter/**/*.py']
|
||||||
|
command = [
|
||||||
|
'python3',
|
||||||
|
'tools/linter/adapters/ufmt_linter.py',
|
||||||
|
'--',
|
||||||
|
'@{{PATHSFILE}}'
|
||||||
|
]
|
||||||
|
exclude_patterns = [
|
||||||
|
'tools/gen_vulkan_spv.py',
|
||||||
|
]
|
||||||
|
init_command = [
|
||||||
|
'python3',
|
||||||
|
'tools/linter/adapters/pip_init.py',
|
||||||
|
'--dry-run={{DRYRUN}}',
|
||||||
|
'black==22.3.0',
|
||||||
|
'ufmt==1.3.3',
|
||||||
|
'usort==1.0.2',
|
||||||
|
]
|
||||||
|
is_formatter = true
|
||||||
|
@ -64,3 +64,6 @@ ignore_missing_imports = True
|
|||||||
|
|
||||||
[mypy-mypy.*]
|
[mypy-mypy.*]
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-usort.*]
|
||||||
|
ignore_missing_imports = True
|
||||||
|
3
mypy.ini
3
mypy.ini
@ -284,3 +284,6 @@ ignore_missing_imports = True
|
|||||||
|
|
||||||
[mypy-dill.*]
|
[mypy-dill.*]
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-usort.*]
|
||||||
|
ignore_missing_imports = True
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
@ -7,7 +7,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, List, NamedTuple, Optional, BinaryIO
|
from typing import Any, BinaryIO, List, NamedTuple, Optional
|
||||||
|
|
||||||
|
|
||||||
IS_WINDOWS: bool = os.name == "nt"
|
IS_WINDOWS: bool = os.name == "nt"
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
Checks that the configuration in .circleci/config.yml has been properly regenerated.
|
Checks that the configuration in .circleci/config.yml has been properly regenerated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import logging
|
|
||||||
import time
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, NamedTuple, Optional
|
from typing import List, NamedTuple, Optional
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
CHECKED_IN_FILE = "config.yml"
|
CHECKED_IN_FILE = "config.yml"
|
||||||
|
@ -7,7 +7,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List, NamedTuple, Optional, Set, Pattern
|
from typing import Any, Dict, List, NamedTuple, Optional, Pattern, Set
|
||||||
|
|
||||||
|
|
||||||
IS_WINDOWS: bool = os.name == "nt"
|
IS_WINDOWS: bool = os.name == "nt"
|
||||||
|
@ -14,14 +14,15 @@ is simply to make sure that there is *some* configuration of ruamel that can rou
|
|||||||
the YAML, not to be prescriptive about it.
|
the YAML, not to be prescriptive about it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import ruamel.yaml # type: ignore[import]
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from io import StringIO
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from io import StringIO
|
||||||
from typing import NamedTuple, Optional
|
from typing import NamedTuple, Optional
|
||||||
|
|
||||||
|
import ruamel.yaml # type: ignore[import]
|
||||||
|
|
||||||
|
|
||||||
class LintSeverity(str, Enum):
|
class LintSeverity(str, Enum):
|
||||||
ERROR = "error"
|
ERROR = "error"
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
Initializer script that installs stuff to pip.
|
Initializer script that installs stuff to pip.
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import shutil
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, NamedTuple, Optional
|
from typing import List, NamedTuple, Optional
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ has valid ownership information in a comment header. Valid means:
|
|||||||
- Each owner label actually exists in PyTorch
|
- Each owner label actually exists in PyTorch
|
||||||
- Each owner label starts with "module: " or "oncall: " or is in ACCEPTABLE_OWNER_LABELS
|
- Each owner label starts with "module: " or "oncall: " or is in ACCEPTABLE_OWNER_LABELS
|
||||||
"""
|
"""
|
||||||
import json
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, Any, Optional, NamedTuple
|
from typing import Any, List, NamedTuple, Optional
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
|
141
tools/linter/adapters/ufmt_linter.py
Normal file
141
tools/linter/adapters/ufmt_linter.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import argparse
|
||||||
|
import concurrent.futures
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, List, NamedTuple, Optional
|
||||||
|
|
||||||
|
from ufmt.core import make_black_config, ufmt_string
|
||||||
|
from usort import Config as UsortConfig
|
||||||
|
|
||||||
|
|
||||||
|
IS_WINDOWS: bool = os.name == "nt"
|
||||||
|
|
||||||
|
|
||||||
|
def eprint(*args: Any, **kwargs: Any) -> None:
|
||||||
|
print(*args, file=sys.stderr, flush=True, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class LintSeverity(str, Enum):
|
||||||
|
ERROR = "error"
|
||||||
|
WARNING = "warning"
|
||||||
|
ADVICE = "advice"
|
||||||
|
DISABLED = "disabled"
|
||||||
|
|
||||||
|
|
||||||
|
class LintMessage(NamedTuple):
|
||||||
|
path: Optional[str]
|
||||||
|
line: Optional[int]
|
||||||
|
char: Optional[int]
|
||||||
|
code: str
|
||||||
|
severity: LintSeverity
|
||||||
|
name: str
|
||||||
|
original: Optional[str]
|
||||||
|
replacement: Optional[str]
|
||||||
|
description: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
def as_posix(name: str) -> str:
|
||||||
|
return name.replace("\\", "/") if IS_WINDOWS else name
|
||||||
|
|
||||||
|
|
||||||
|
def format_error_message(filename: str, err: Exception) -> LintMessage:
|
||||||
|
return LintMessage(
|
||||||
|
path=filename,
|
||||||
|
line=None,
|
||||||
|
char=None,
|
||||||
|
code="UFMT",
|
||||||
|
severity=LintSeverity.ADVICE,
|
||||||
|
name="command-failed",
|
||||||
|
original=None,
|
||||||
|
replacement=None,
|
||||||
|
description=(f"Failed due to {err.__class__.__name__}:\n{err}"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def check_file(
|
||||||
|
filename: str,
|
||||||
|
) -> List[LintMessage]:
|
||||||
|
with open(filename, "rb") as f:
|
||||||
|
original = f.read().decode("utf-8")
|
||||||
|
|
||||||
|
try:
|
||||||
|
path = Path(filename)
|
||||||
|
|
||||||
|
usort_config = UsortConfig.find(path)
|
||||||
|
black_config = make_black_config(path)
|
||||||
|
|
||||||
|
# Use UFMT API to call both usort and black
|
||||||
|
replacement = ufmt_string(
|
||||||
|
path=path,
|
||||||
|
content=original,
|
||||||
|
usort_config=usort_config,
|
||||||
|
black_config=black_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
if original == replacement:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [
|
||||||
|
LintMessage(
|
||||||
|
path=filename,
|
||||||
|
line=None,
|
||||||
|
char=None,
|
||||||
|
code="UFMT",
|
||||||
|
severity=LintSeverity.WARNING,
|
||||||
|
name="format",
|
||||||
|
original=original,
|
||||||
|
replacement=replacement,
|
||||||
|
description="Run `lintrunner -a` to apply this patch.",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
except Exception as err:
|
||||||
|
return [format_error_message(filename, err)]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Format files with ufmt (black + usort).",
|
||||||
|
fromfile_prefix_chars="@",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--verbose",
|
||||||
|
action="store_true",
|
||||||
|
help="verbose logging",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"filenames",
|
||||||
|
nargs="+",
|
||||||
|
help="paths to lint",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
format="<%(threadName)s:%(levelname)s> %(message)s",
|
||||||
|
level=logging.NOTSET
|
||||||
|
if args.verbose
|
||||||
|
else logging.DEBUG
|
||||||
|
if len(args.filenames) < 1000
|
||||||
|
else logging.INFO,
|
||||||
|
stream=sys.stderr,
|
||||||
|
)
|
||||||
|
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(
|
||||||
|
max_workers=os.cpu_count(),
|
||||||
|
thread_name_prefix="Thread",
|
||||||
|
) as executor:
|
||||||
|
futures = {executor.submit(check_file, x): x for x in args.filenames}
|
||||||
|
for future in concurrent.futures.as_completed(futures):
|
||||||
|
try:
|
||||||
|
for lint_message in future.result():
|
||||||
|
print(json.dumps(lint_message._asdict()), flush=True)
|
||||||
|
except Exception:
|
||||||
|
logging.critical('Failed at "%s".', futures[future])
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -6,11 +6,12 @@ for how to configure them.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import boto3 # type: ignore[import]
|
|
||||||
import json
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import boto3 # type: ignore[import]
|
||||||
|
|
||||||
|
|
||||||
def compute_file_sha256(path: str) -> str:
|
def compute_file_sha256(path: str) -> str:
|
||||||
|
@ -5,12 +5,12 @@ Any job with a specific `sync-tag` must match all other jobs with the same `sync
|
|||||||
import argparse
|
import argparse
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
|
||||||
from typing import Iterable, Any, Optional, NamedTuple, Dict
|
|
||||||
from enum import Enum
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from enum import Enum
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Iterable, NamedTuple, Optional
|
||||||
|
|
||||||
from yaml import load, CSafeLoader, dump
|
from yaml import CSafeLoader, dump, load
|
||||||
|
|
||||||
|
|
||||||
class LintSeverity(str, Enum):
|
class LintSeverity(str, Enum):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user