Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions src/rapids_pre_commit_hooks/alpha_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: Apache-2.0

import argparse
import contextlib
import dataclasses
import os
import re
from functools import cache, total_ordering
Expand All @@ -13,6 +15,7 @@
from rapids_metadata.remote import fetch_latest

from .lint import Linter, LintMain
from .utils.yaml import Anchor, is_reference_anchor
from .utils.dependencies_yaml import Handler, traverse_dependencies_yaml

ALPHA_SPECIFIER: str = ">=0.0.0a0"
Expand Down Expand Up @@ -48,16 +51,37 @@ def strip_cuda_suffix(args: argparse.Namespace, name: str) -> str:


class AlphaSpecHandler(Handler):
@dataclasses.dataclass
class PackagesContext:
packages_is_reference_anchor: bool

def __init__(self, linter: Linter, args: argparse.Namespace):
self.linter = linter
self.args = args

def handle_packages(
self,
common_or_matrices_item_context: "Any", # noqa: ARG002
anchor: "Optional[Anchor]", # noqa: ARG002
key: "yaml.Node", # noqa: ARG002
value: "yaml.Node", # noqa: ARG002
) -> "contextlib.nullcontext[AlphaSpecHandler.PackagesContext]":
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return contextlib.nullcontext(
AlphaSpecHandler.PackagesContext(is_reference_anchor(anchor))
)

def handle_package(
self,
packages_context: "Any", # noqa: ARG002
anchor: "Optional[str]",
packages_context: "AlphaSpecHandler.PackagesContext", # noqa: ARG002
anchor: "Optional[Anchor]",
node: "yaml.Node",
) -> None:
if (
packages_context.packages_is_reference_anchor
or is_reference_anchor(anchor)
):
return

@total_ordering
class SpecPriority:
def __init__(self, spec: str):
Expand Down Expand Up @@ -102,7 +126,7 @@ def create_specifier_string(specifiers: set[str]) -> str:
).add_replacement(
(node.start_mark.index, node.end_mark.index),
str(
(f"&{anchor} " if anchor else "")
(f"&{anchor.anchor_name} " if anchor else "")
+ req.name
+ create_specifier_string(
{str(s) for s in req.specifier} | {ALPHA_SPECIFIER},
Expand All @@ -116,7 +140,7 @@ def create_specifier_string(specifiers: set[str]) -> str:
).add_replacement(
(node.start_mark.index, node.end_mark.index),
str(
(f"&{anchor} " if anchor else "")
(f"&{anchor.anchor_name} " if anchor else "")
+ req.name
+ create_specifier_string(
{str(s) for s in req.specifier} - {ALPHA_SPECIFIER},
Expand Down
53 changes: 43 additions & 10 deletions src/rapids_pre_commit_hooks/dependencies/cuda_suffixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

from packaging.requirements import InvalidRequirement, Requirement

from rapids_pre_commit_hooks.utils.dependencies_yaml import (
from ..utils.dependencies_yaml import (
Handler,
)
from ..utils.yaml import Anchor, is_reference_anchor
from rapids_metadata.remote import fetch_latest

if TYPE_CHECKING:
Expand All @@ -21,7 +22,7 @@

import yaml

from rapids_pre_commit_hooks.lint import Linter
from ..lint import Linter
from rapids_metadata.metadata import RAPIDSMetadata, RAPIDSVersion


Expand Down Expand Up @@ -82,6 +83,14 @@ class MatricesItemContext:
default_factory=list
)

@dataclass
class PackagesContext:
parent_context: (
"CUDASuffixedHandler.CommonItemContext | "
"CUDASuffixedHandler.MatricesItemContext"
)
packages_is_reference_anchor: bool

def __init__(self, linter: "Linter", args: "argparse.Namespace") -> None:
self.linter = linter
self.args = args
Expand All @@ -94,7 +103,7 @@ def handle_output_type(
),
item: "yaml.Node",
) -> None:
if item.value in {"requirements", "pyproject"}:
if item.value in {"requirements", "constraints", "pyproject"}:
output_types_context.has_python_output_type = True

@contextlib.contextmanager
Expand Down Expand Up @@ -321,15 +330,34 @@ def handle_matrix_item(
matrix_context.cuda_node = value
matrix_context.cuda_major = int(match.group("major"))

def handle_package(
def handle_packages(
self,
packages_context: (
common_or_matrices_item_context: (
"CUDASuffixedHandler.CommonItemContext | "
"CUDASuffixedHandler.MatricesItemContext"
),
anchor: "Optional[str]",
anchor: "Optional[Anchor]",
key: "yaml.Node", # noqa: ARG002
value: "yaml.Node", # noqa: ARG002
) -> "contextlib.nullcontext[CUDASuffixedHandler.PackagesContext]":
return contextlib.nullcontext(
CUDASuffixedHandler.PackagesContext(
common_or_matrices_item_context, is_reference_anchor(anchor)
)
)

def handle_package(
self,
packages_context: "CUDASuffixedHandler.PackagesContext",
anchor: "Optional[Anchor]",
item: "yaml.Node",
) -> None:
if (
packages_context.packages_is_reference_anchor
or is_reference_anchor(anchor)
):
return

try:
req = Requirement(item.value)
except InvalidRequirement:
Expand All @@ -341,14 +369,19 @@ def handle_package(
)

if req.name in cuda_suffixed_packages:
packages_context.suspicious_unsuffixed_packages.append(
(req.name, anchor, item)
packages_context.parent_context.suspicious_unsuffixed_packages.append(
(req.name, anchor.anchor_name if anchor else None, item)
)
elif (
match := re.search(
r"^(?P<package>.*)(?P<suffix>-cu[0-9]+)$", req.name
)
) and match.group("package") in cuda_suffixed_packages:
packages_context.suspicious_suffixed_packages.append(
(match.group("package"), match.group("suffix"), anchor, item)
packages_context.parent_context.suspicious_suffixed_packages.append(
(
match.group("package"),
match.group("suffix"),
anchor.anchor_name if anchor else None,
item,
)
)
56 changes: 36 additions & 20 deletions src/rapids_pre_commit_hooks/dependencies/use_cuda_wheels.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@

from packaging.requirements import InvalidRequirement, Requirement

from rapids_pre_commit_hooks.utils.dependencies_yaml import (
from ..utils.dependencies_yaml import (
Handler,
)
from ..utils.yaml import Anchor, is_reference_anchor

if TYPE_CHECKING:
import argparse
from collections.abc import Generator

import yaml

from rapids_pre_commit_hooks.lint import Linter
from ..lint import Linter


def is_nvidia_library_package(req: "Requirement") -> bool:
Expand Down Expand Up @@ -72,13 +73,18 @@ def is_cupy_ctk_package(req: "Requirement") -> bool:

class UseCUDAWheelsHandler(Handler):
@dataclass
class Context:
class CommonOrMatricesItemContext:
has_use_cuda_wheels: bool = False
use_cuda_wheels_node: "Optional[yaml.Node]" = None
suspicious_packages: "list[tuple[yaml.Node, str]]" = field(
default_factory=list
)

@dataclass
class PackagesContext:
parent_context: "UseCUDAWheelsHandler.CommonOrMatricesItemContext"
packages_is_reference_anchor: bool

def __init__(self, linter: "Linter", args: "argparse.Namespace"):
self.linter = linter
self.args = args
Expand All @@ -89,8 +95,8 @@ def handle_common(
dependency_set_context: "Any", # noqa: ARG002
key: "yaml.Node",
value: "yaml.Node", # noqa: ARG002
) -> "Generator[UseCUDAWheelsHandler.Context]":
context = UseCUDAWheelsHandler.Context()
) -> "Generator[UseCUDAWheelsHandler.CommonOrMatricesItemContext]":
context = UseCUDAWheelsHandler.CommonOrMatricesItemContext()
yield context

for node, name in context.suspicious_packages:
Expand All @@ -109,8 +115,8 @@ def handle_matrices_item(
self,
matrices_context: "Any", # noqa: ARG002
item: "yaml.Node", # noqa: ARG002
) -> "Generator[UseCUDAWheelsHandler.Context]":
context = UseCUDAWheelsHandler.Context()
) -> "Generator[UseCUDAWheelsHandler.CommonOrMatricesItemContext]":
context = UseCUDAWheelsHandler.CommonOrMatricesItemContext()
yield context

if not context.has_use_cuda_wheels:
Expand All @@ -130,19 +136,18 @@ def handle_matrices_item(
'use_cuda_wheels: "true" instead',
)

@contextlib.contextmanager
def handle_matrix(
self,
matrices_item_context: "UseCUDAWheelsHandler.Context",
matrices_item_context: "UseCUDAWheelsHandler.CommonOrMatricesItemContext", # noqa: E501
key: "yaml.Node",
value: "yaml.Node", # noqa: ARG002
) -> "Generator[UseCUDAWheelsHandler.Context]":
) -> "contextlib.nullcontext[UseCUDAWheelsHandler.CommonOrMatricesItemContext]": # noqa: E501
matrices_item_context.use_cuda_wheels_node = key
yield matrices_item_context
return contextlib.nullcontext(matrices_item_context)

def handle_matrix_item(
self,
matrix_context: "UseCUDAWheelsHandler.Context",
matrix_context: "UseCUDAWheelsHandler.CommonOrMatricesItemContext",
key: "yaml.Node",
value: "yaml.Node",
) -> None:
Expand All @@ -151,30 +156,41 @@ def handle_matrix_item(
if value.value == "true":
matrix_context.has_use_cuda_wheels = True

@contextlib.contextmanager
def handle_packages(
self,
common_or_matrices_item_context: "UseCUDAWheelsHandler.Context",
common_or_matrices_item_context: "UseCUDAWheelsHandler.CommonOrMatricesItemContext", # noqa: E501
anchor: "Optional[Anchor]",
key: "yaml.Node",
value: "yaml.Node", # noqa: ARG002
) -> "Generator[UseCUDAWheelsHandler.Context]":
) -> "contextlib.nullcontext[UseCUDAWheelsHandler.PackagesContext]":
if common_or_matrices_item_context.use_cuda_wheels_node is None:
common_or_matrices_item_context.use_cuda_wheels_node = key
yield common_or_matrices_item_context
context = UseCUDAWheelsHandler.PackagesContext(
common_or_matrices_item_context, is_reference_anchor(anchor)
)
return contextlib.nullcontext(context)

def handle_package(
self,
packages_context: "UseCUDAWheelsHandler.Context",
anchor: "Optional[str]", # noqa: ARG002
packages_context: "UseCUDAWheelsHandler.PackagesContext",
anchor: "Optional[Anchor]",
item: "yaml.Node",
) -> None:
if (
packages_context.packages_is_reference_anchor
or is_reference_anchor(anchor)
):
return

try:
req = Requirement(item.value)
except InvalidRequirement:
return
if is_nvidia_library_package(req):
packages_context.suspicious_packages.append((item, req.name))
packages_context.parent_context.suspicious_packages.append(
(item, req.name)
)
elif is_cupy_ctk_package(req):
packages_context.suspicious_packages.append(
packages_context.parent_context.suspicious_packages.append(
(item, f"{req.name}[ctk]")
)
40 changes: 22 additions & 18 deletions src/rapids_pre_commit_hooks/utils/dependencies_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

import yaml

from .yaml import AnchorPreservingLoader, check_and_mark_anchor, node_has_type
from .yaml import (
Anchor,
AnchorPreservingLoader,
check_and_mark_anchor,
node_has_type,
)

if TYPE_CHECKING:
from collections.abc import Generator, Iterable
Expand Down Expand Up @@ -114,6 +119,7 @@ def handle_matrix_item(
def handle_packages(
self,
common_or_matrices_item_context: "Any",
anchor: "Optional[Anchor]", # noqa: ARG002
key: "yaml.Node", # noqa: ARG002
value: "yaml.Node", # noqa: ARG002
) -> "contextlib.AbstractContextManager[Any]":
Expand All @@ -122,7 +128,7 @@ def handle_packages(
def handle_package(
self,
packages_context: "Any", # noqa: ARG002
anchor: "Optional[str]", # noqa: ARG002
anchor: "Optional[Anchor]", # noqa: ARG002
item: "yaml.Node", # noqa: ARG002
) -> None:
pass
Expand Down Expand Up @@ -299,9 +305,8 @@ def traverse_package(
node: "yaml.Node",
) -> None:
if node_has_type(node, "str"):
descend, anchor = check_and_mark_anchor(anchors, used_anchors, node)
if descend:
handler.handle_package(packages_context, anchor, node)
anchor = check_and_mark_anchor(anchors, used_anchors, node)
handler.handle_package(packages_context, anchor, node)


def traverse_packages(
Expand All @@ -313,19 +318,18 @@ def traverse_packages(
node: "yaml.Node",
) -> None:
if node_has_type(node, "seq"):
descend, _ = check_and_mark_anchor(anchors, used_anchors, node)
if descend:
with handler.handle_packages(
common_or_matrices_item_context, key_node, node
) as packages_context:
for package in node.value:
traverse_package(
handler,
packages_context,
anchors,
used_anchors,
package,
)
anchor = check_and_mark_anchor(anchors, used_anchors, node)
with handler.handle_packages(
common_or_matrices_item_context, anchor, key_node, node
) as packages_context:
for package in node.value:
traverse_package(
handler,
packages_context,
anchors,
used_anchors,
package,
)


def traverse_output_type(
Expand Down
Loading
Loading