LibCST/scripts/check_copyright.py
Amethyst Reese 6a7b82e2b6 PEP 621 + hatch to run tests/lint/etc
Moves PEP 621 metadata from `setup.py` and `requirements*.txt` into the
`[project]` table of `pyproject.toml`. This enables using hatch as a
task runner for the project, where previously one would need to remember
a bunch of different commands, or repeatedly consult the readme's
developer guide to find all of the relevant commands.

This creates the following hatch commands:

- docs
- fixtures
- format
- lint
- test
- typecheck

It also updates all of the github actions workflows to use the
appropriate hatch commands, and the readme's developer guide, so that
there is only one source of truth for what constitutes running tests.

The "test" workflows now drop the matrix distinction between "pure" or
"native", and run tests in both modes from a single build.

ghstack-source-id: 8834da7825
Pull Request resolved: https://github.com/Instagram/LibCST/pull/893
2023-03-14 19:37:41 -07:00

58 lines
1.7 KiB
Python

# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import re
import sys
from pathlib import Path
from subprocess import run
from typing import Iterable, List, Pattern
# Use the copyright header from this file as the benchmark for all files
EXPECTED_HEADER: str = "\n".join(
line for line in Path(__file__).read_text().splitlines()[:4]
)
EXCEPTION_PATTERNS: List[Pattern[str]] = [
re.compile(pattern)
for pattern in (
r"^native/libcst/tests/fixtures/",
r"^libcst/_add_slots\.py$",
r"^libcst/tests/test_(e2e|fuzz)\.py$",
r"^libcst/_parser/base_parser\.py$",
r"^libcst/_parser/parso/utils\.py$",
r"^libcst/_parser/parso/pgen2/(generator|grammar_parser)\.py$",
r"^libcst/_parser/parso/python/(py_token|tokenize)\.py$",
r"^libcst/_parser/parso/tests/test_(fstring|tokenize|utils)\.py$",
)
]
def tracked_files() -> Iterable[Path]:
proc = run(
["git", "ls-tree", "-r", "--name-only", "HEAD"],
check=True,
capture_output=True,
encoding="utf-8",
)
yield from (
path
for line in proc.stdout.splitlines()
if not any(pattern.search(line) for pattern in EXCEPTION_PATTERNS)
if (path := Path(line)) and path.is_file() and path.suffix in (".py", ".sh")
)
def main() -> None:
error = False
for path in tracked_files():
content = path.read_text("utf-8")
if EXPECTED_HEADER not in content:
print(f"Missing or incomplete copyright in {path}")
error = True
sys.exit(1 if error else 0)
if __name__ == "__main__":
main()