Skip to content

Single Rule Logic

DeprecatedRule

A specific rule that checks if the package is deprecated.

Source code in searchv2/rules.py
class DeprecatedRule(ScoreRule):
    """
    A specific rule that checks if the package is deprecated.
    """

    name: str = "Deprecated Rule"
    description: str = "Check if the package is deprecated"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/deprecated"

    def check(self, package: Package) -> CheckResult:
        """
        Check if the package is deprecated.
        Returns a full score and a success message if the package is not deprecated,
        or a zero score and an error message otherwise.
        """
        if not package.is_deprecated:
            return CheckResult(
                score=self.max_score, message="Package is not deprecated."
            )
        else:
            return CheckResult(score=0, message="Package is deprecated.")

DescriptionRule

A specific rule that checks if the package has a description.

Source code in searchv2/rules.py
class DescriptionRule(ScoreRule):
    """
    A specific rule that checks if the package has a description.
    """

    name: str = "Description Rule"
    description: str = "Check if the package has a description"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/description"

    def check(self, package: Package) -> CheckResult:
        """
        Check if the package has a description.
        Returns a full score and a success message if the package has a description,
        or a zero score and an error message otherwise.
        """
        if package.repo_description and package.repo_description.strip():
            return CheckResult(
                score=self.max_score, message="Package has a description."
            )
        else:
            return CheckResult(score=0, message="Package has no description.")

DownloadsRule

A specific rule that scores based on the number of PyPi downloads.

Source code in searchv2/rules.py
class DownloadsRule(ScoreRule):
    """
    A specific rule that scores based on the number of PyPi downloads.
    """

    name: str = "Downloads Rule"
    description: str = "Score based on the number of PyPi downloads"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/downloads"

    def check(self, package: Package) -> CheckResult:
        """
        Check the number of PyPi downloads for the package.
        Returns a score and a success message based on the number of downloads,
        or a zero score and an error message if no downloads data is found.
        """
        if package.pypi_downloads:
            score = min(int(package.pypi_downloads / 1_000), self.max_score)
            return CheckResult(
                score=score,
                message=f"Package has {package.pypi_downloads} PyPi downloads.",
            )
        else:
            return CheckResult(
                score=0, message="No PyPi downloads data for the package."
            )

ForkRule

A specific rule that scores based on the number of repository forks.

Source code in searchv2/rules.py
class ForkRule(ScoreRule):
    """
    A specific rule that scores based on the number of repository forks.
    """

    name: str = "Fork Rule"
    description: str = "Score based on the number of forks"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/fork"

    def check(self, package: Package) -> CheckResult:
        """
        Check the number of forks for the package's repository.
        Returns a score and a success message based on the number of forks,
        or a zero score and an error message if no forks data is found.
        """
        if package.repo_forks:
            score = min(package.repo_forks, self.max_score)
            return CheckResult(
                score=score,
                message=f"Package repository has {package.repo_forks} forks.",
            )
        else:
            return CheckResult(
                score=0, message="No forks data for the package repository."
            )

UsageCountRule

A specific rule that scores based on the usage count of the package.

Source code in searchv2/rules.py
class UsageCountRule(ScoreRule):
    """
    A specific rule that scores based on the usage count of the package.
    """

    name: str = "Usage Count Rule"
    description: str = "Score based on the usage count"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/usage_count"

    def check(self, package: Package) -> CheckResult:
        """
        Check the usage count of the package.
        Returns a score and a success message based on the usage count,
        or a zero score and an error message if no usage data is found.
        """
        usage_count = package.usage.count()
        if usage_count:
            score = min(usage_count, self.max_score)
            return CheckResult(
                score=score, message=f"Package has a usage count of {usage_count}."
            )
        else:
            return CheckResult(score=0, message="No usage data found for the package.")

WatchersRule

A specific rule that scores based on the number of watchers of the package's repository.

Source code in searchv2/rules.py
class WatchersRule(ScoreRule):
    """
    A specific rule that scores based on the number of watchers of the package's repository.
    """

    name: str = "Watchers Rule"
    description: str = "Score based on the number of watchers"
    max_score: int = 20
    documentation_url: str = f"{DOCS_URL}/rules/watchers"

    def check(self, package: Package) -> CheckResult:
        """
        Check the number of watchers for the package's repository.
        Returns a score and a success message based on the number of watchers,
        or a zero score and an error message if no watchers data is found.
        """
        if package.repo_watchers:
            score = min(package.repo_watchers, self.max_score)
            return CheckResult(
                score=score,
                message=f"Package repository has {package.repo_watchers} watchers.",
            )
        else:
            return CheckResult(
                score=0, message="No watchers data for the package repository."
            )

Group Rule Logic

ScoreRuleGroup

A group of rules, which checks a package by applying each rule in the group, and returns a normalized total score and a combined message from all checks.

Attributes:

Name Type Description
rules list[ScoreRule]

A list of ScoreRule objects in this group.

Methods:

Name Description
check

Checks the given package against each scoring rule in this group, and returns a CheckResult instance with the normalized total score and a combined message.

Source code in searchv2/rules.py
class ScoreRuleGroup(ScoreRule):
    """
    A group of rules, which checks a package by applying each rule in the group,
    and returns a normalized total score and a combined message from all checks.

    Attributes:
        rules: A list of ScoreRule objects in this group.

    Methods:
        check: Checks the given package against each scoring rule in this group, and returns a CheckResult instance
               with the normalized total score and a combined message.
    """

    rules: list[ScoreRule]

    def check(self, package: Package) -> CheckResult:
        """
        Checks the given package against each scoring rule in this group, and returns a CheckResult instance
        with the normalized total score and a combined message.

        The total score is calculated by summing up the scores from each rule.
        It is then normalized by dividing it by the sum of maximum scores of all the rules in the group, and multiplying
        by the maximum score of this group.

        If the sum of the maximum scores of all the rules in the group is zero, the normalized total score is set to zero.

        Args:
            package: The package to check.

        Returns:
            A CheckResult instance with the normalized total score and a combined message from all checks.
        """
        results = [rule.check(package=package) for rule in self.rules]
        total_score = sum(result.score for result in results)
        max_possible_score = sum(rule.max_score for rule in self.rules)

        # Normalize the total score to the max score of this group.
        normalized_score = (
            (total_score / max_possible_score) * self.max_score
            if max_possible_score > 0
            else 0
        )

        # Combine all the messages from the checks.
        messages = [result.message for result in results]

        return CheckResult(score=int(normalized_score), message=" ".join(messages))