Skip to content

Commit

Permalink
Upgrade Ruff creates
Browse files Browse the repository at this point in the history
  • Loading branch information
max-muoto committed Jan 28, 2025
1 parent c1d53f6 commit 4aa4a39
Show file tree
Hide file tree
Showing 27 changed files with 2,629 additions and 1,159 deletions.
1,437 changes: 1,256 additions & 181 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ pyo3 = { version = "0.22.5", features = ["abi3-py37"] }
regex = "1.11.1"
once_cell = "1.20.2"
walkdir = "2.5.0"
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.5" }
ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.5" }
ruff_source_file = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.5" }
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "0.9.3" }
ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", tag = "0.9.3" }
ruff_linter = { git = "https://github.com/astral-sh/ruff.git", tag = "0.9.3" }
cached = { version = "0.54.0", features = ["disk_store"] }
globset = "0.4.15"
toml = "0.8.19"
thiserror = "2.0.7"
serde = { version = "1.0.216", features = ["derive"] }
glob = "0.3.2"
petgraph = "0.7.0"
petgraph = "0.7.1"
serde_json = "1.0.134"
tempfile = "3.15.0"
lsp-server = "0.7.7"
Expand All @@ -33,6 +33,7 @@ rayon = "1.10.0"
parking_lot = "0.12.3"
itertools = "0.14.0"
toml_edit = "0.22.22"
console = "0.15.10"

[features]
extension-module = ["pyo3/extension-module"]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ dev = [
"pip==24.0",
# Code Quality
"pyright==1.1.389",
"ruff==0.8.3",
"ruff==0.9.3",
# Build/Release
"setuptools==69.5.1; python_version > '3.7'",
"twine==5.1.1; python_version > '3.7'",
Expand Down
4 changes: 2 additions & 2 deletions python/tach/check_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from tach.errors import TachError
from tach.extension import (
ExternalCheckDiagnostics,
Diagnostic,
check_external_dependencies,
set_excluded_paths,
)
Expand Down Expand Up @@ -34,7 +34,7 @@ def check_external(
project_root: Path,
project_config: ProjectConfig,
exclude_paths: list[str],
) -> ExternalCheckDiagnostics:
) -> list[Diagnostic]:
set_excluded_paths(
project_root=str(project_root),
exclude_paths=exclude_paths,
Expand Down
175 changes: 21 additions & 154 deletions python/tach/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
check_computation_cache,
create_computation_cache_key,
detect_unused_dependencies,
format_diagnostics,
run_server,
serialize_diagnostics_json,
update_computation_cache,
)
from tach.filesystem import install_pre_commit
Expand All @@ -42,101 +44,9 @@
)
from tach.sync import sync_project
from tach.test import run_affected_tests
from tach.utils.display import create_clickable_link

if TYPE_CHECKING:
from tach.extension import BoundaryError, UnusedDependencies


def build_error_message(error: BoundaryError, source_roots: list[Path]) -> str:
absolute_error_path = next(
(
source_root / error.file_path
for source_root in source_roots
if (source_root / error.file_path).exists()
),
None,
)

if absolute_error_path is None:
# This is an unexpected case,
# all errors should have originated from within a source root
error_location = error.file_path
else:
error_location = create_clickable_link(
absolute_error_path,
display_path=error.file_path,
line=error.line_number,
)

error_template = (
f"{icons.FAIL} {BCOLORS.FAIL}{error_location}{BCOLORS.ENDC}{BCOLORS.WARNING}: "
f"{{message}} {BCOLORS.ENDC}"
)
warning_template = (
f"{icons.WARNING} {BCOLORS.FAIL}{error_location}{BCOLORS.ENDC}{BCOLORS.WARNING}: "
f"{{message}} {BCOLORS.ENDC}"
)
error_info = error.error_info
if error_info.is_deprecated():
return warning_template.format(message=error_info.to_pystring())
return error_template.format(message=error_info.to_pystring())


def print_warnings(warning_list: list[str]) -> None:
for warning in warning_list:
print(f"{BCOLORS.WARNING}{warning}{BCOLORS.ENDC}", file=sys.stderr)


def print_errors(error_list: list[str]) -> None:
for error in error_list:
print(f"{BCOLORS.FAIL}{error}{BCOLORS.ENDC}", file=sys.stderr)


def print_boundary_errors(
error_list: list[BoundaryError], source_roots: list[Path]
) -> None:
if not error_list:
return

interface_errors: list[BoundaryError] = []
dependency_errors: list[BoundaryError] = []
for error in sorted(error_list, key=lambda e: e.file_path):
if error.error_info.is_interface_error():
interface_errors.append(error)
else:
dependency_errors.append(error)

if interface_errors:
print(f"{BCOLORS.FAIL}Interface Errors:{BCOLORS.ENDC}", file=sys.stderr)
for error in interface_errors:
print(
build_error_message(error, source_roots=source_roots),
file=sys.stderr,
)
print(
f"{BCOLORS.WARNING}\nIf you intended to change an interface, edit the '[[interfaces]]' section of {CONFIG_FILE_NAME}.toml."
f"\nOtherwise, remove any disallowed imports and consider refactoring.\n{BCOLORS.ENDC}",
file=sys.stderr,
)

if dependency_errors:
print(f"{BCOLORS.FAIL}Dependency Errors:{BCOLORS.ENDC}", file=sys.stderr)
has_real_errors = False
for error in dependency_errors:
if not error.error_info.is_deprecated():
has_real_errors = True
print(
build_error_message(error, source_roots=source_roots),
file=sys.stderr,
)
print(file=sys.stderr)
if has_real_errors:
print(
f"{BCOLORS.WARNING}If you intended to add a new dependency, run 'tach sync' to update your module configuration."
f"\nOtherwise, remove any disallowed imports and consider refactoring.\n{BCOLORS.ENDC}",
file=sys.stderr,
)
from tach.extension import UnusedDependencies


def print_unused_dependencies(
Expand Down Expand Up @@ -246,46 +156,6 @@ def print_visibility_errors(
)


def print_undeclared_dependencies(
undeclared_dependencies: dict[str, list[str]],
) -> None:
any_undeclared = False
for file_path, dependencies in undeclared_dependencies.items():
if dependencies:
any_undeclared = True
print(
f"{icons.FAIL}: {BCOLORS.FAIL}Undeclared dependencies in {BCOLORS.ENDC}{BCOLORS.WARNING}'{file_path}'{BCOLORS.ENDC}:"
)
for dependency in dependencies:
print(f"\t{BCOLORS.FAIL}{dependency}{BCOLORS.ENDC}")
if any_undeclared:
print(
f"{BCOLORS.WARNING}\nAdd the undeclared dependencies to the corresponding pyproject.toml file, "
f"or consider ignoring the dependencies by adding them to the 'external.exclude' list in {CONFIG_FILE_NAME}.toml.\n{BCOLORS.ENDC}",
file=sys.stderr,
)


def print_unused_external_dependencies(
unused_dependencies: dict[str, list[str]],
) -> None:
any_unused = False
for pyproject_path, dependencies in unused_dependencies.items():
if dependencies:
any_unused = True
print(
f"{icons.WARNING} {BCOLORS.WARNING}Unused dependencies from project at {BCOLORS.OKCYAN}'{pyproject_path}'{BCOLORS.ENDC}{BCOLORS.ENDC}:"
)
for dependency in dependencies:
print(f"\t{BCOLORS.WARNING}{dependency}{BCOLORS.ENDC}")
if any_unused:
print(
f"{BCOLORS.OKCYAN}\nRemove the unused dependencies from the corresponding pyproject.toml file, "
f"or consider ignoring the dependencies by adding them to the 'external.exclude' list in {CONFIG_FILE_NAME}.toml.\n{BCOLORS.ENDC}",
file=sys.stderr,
)


def add_base_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument(
"-e",
Expand Down Expand Up @@ -626,33 +496,28 @@ def tach_check(
try:
exact |= project_config.exact

check_result = check(
diagnostics = check(
project_root=project_root,
project_config=project_config,
dependencies=dependencies,
interfaces=interfaces,
exclude_paths=exclude_paths,
)
has_errors = any(diagnostic.is_error() for diagnostic in diagnostics)

if output_format == "json":
try:
print(check_result.serialize_json(pretty_print=True))
print(serialize_diagnostics_json(diagnostics, pretty_print=True))
except ValueError as e:
json.dump({"error": str(e)}, sys.stdout)
sys.exit(1 if len(check_result.errors) > 0 else 0)

if check_result.warnings:
print_warnings(check_result.warnings)

source_roots = [
project_root / source_root for source_root in project_config.source_roots
]
sys.exit(1 if has_errors else 0)

print_boundary_errors(
check_result.errors + check_result.deprecated_warnings,
source_roots=source_roots,
)
exit_code = 1 if len(check_result.errors) > 0 else 0
if diagnostics:
print(
format_diagnostics(project_root=project_root, diagnostics=diagnostics),
file=sys.stderr,
)
exit_code = 1 if has_errors else 0

# If we're checking in exact mode, we want to verify that there are no unused dependencies
if dependencies and exact:
Expand Down Expand Up @@ -697,18 +562,20 @@ def tach_check_external(
},
)
try:
result = check_external(
diagnostics = check_external(
project_root=project_root,
project_config=project_config,
exclude_paths=exclude_paths,
)

print_warnings(result.warnings)
print_errors(result.errors)
print_unused_external_dependencies(result.unused_dependencies)
print_undeclared_dependencies(result.undeclared_dependencies)
if diagnostics:
print(
format_diagnostics(project_root=project_root, diagnostics=diagnostics),
file=sys.stderr,
)

if result.errors or result.undeclared_dependencies:
has_errors = any(diagnostic.is_error() for diagnostic in diagnostics)
if has_errors:
sys.exit(1)
else:
print(
Expand Down
71 changes: 37 additions & 34 deletions python/tach/extension.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ def get_normalized_imports(
def set_excluded_paths(
project_root: str, exclude_paths: list[str], use_regex_matching: bool
) -> None: ...
def check_external_dependencies(
project_root: str,
project_config: ProjectConfig,
module_mappings: dict[str, list[str]],
stdlib_modules: list[str],
) -> ExternalCheckDiagnostics: ...
def create_dependency_report(
project_root: str,
project_config: ProjectConfig,
Expand Down Expand Up @@ -60,7 +54,17 @@ def check(
dependencies: bool,
interfaces: bool,
exclude_paths: list[str],
) -> CheckDiagnostics: ...
) -> list[Diagnostic]: ...
def check_external_dependencies(
project_root: str,
project_config: ProjectConfig,
module_mappings: dict[str, list[str]],
stdlib_modules: list[str],
) -> list[Diagnostic]: ...
def format_diagnostics(
project_root: Path,
diagnostics: list[Diagnostic],
) -> str: ...
def detect_unused_dependencies(
project_root: Path,
project_config: ProjectConfig,
Expand All @@ -75,38 +79,37 @@ def sync_project(
def run_server(project_root: Path, project_config: ProjectConfig) -> None: ...
def serialize_modules_json(modules: list[ModuleConfig]) -> str: ...

class ErrorInfo:
class Diagnostic:
def is_code(self) -> bool: ...
def is_configuration(self) -> bool: ...
def is_dependency_error(self) -> bool: ...
def is_interface_error(self) -> bool: ...
def to_pystring(self) -> str: ...
def is_warning(self) -> bool: ...
def is_error(self) -> bool: ...
def is_deprecated(self) -> bool: ...
def usage_module(self) -> str | None: ...
def definition_module(self) -> str | None: ...
def to_string(self) -> str: ...
def pyfile_path(self) -> str | None: ...
def pyline_number(self) -> int | None: ...

def serialize_diagnostics_json(
diagnostics: list[Diagnostic], pretty_print: bool
) -> str: ...

class BoundaryError:
file_path: Path
line_number: int
import_mod_path: str
error_info: ErrorInfo

class CheckDiagnostics:
errors: list[BoundaryError]
deprecated_warnings: list[BoundaryError]
warnings: list[str]

def serialize_json(self, pretty_print: bool = False) -> str: ...

class ExternalCheckDiagnostics:
undeclared_dependencies: dict[str, list[str]]
unused_dependencies: dict[str, list[str]]
errors: list[str]
warnings: list[str]
ErrorKind = Literal["DEPENDENCY", "INTERFACE"]

def __new__(
cls,
undeclared_dependencies: dict[str, list[str]],
unused_dependencies: dict[str, list[str]],
errors: list[str],
warnings: list[str],
) -> ExternalCheckDiagnostics: ...
class UsageError:
file: str
line_number: int
member: str
# The module that contains the usage
usage_module: str
# The module that contains the definition
definition_module: str
error_type: ErrorKind

def into_usage_errors(diagnostics: list[Diagnostic]) -> list[UsageError]: ...

class DependencyConfig:
path: str
Expand Down
Loading

0 comments on commit 4aa4a39

Please sign in to comment.