Skip to content

Commit

Permalink
Implement is_unavailable status
Browse files Browse the repository at this point in the history
Add new functions to the Package and PackageVersion models to
determine whether a package or package version is unavailable.

A package is considered unavailable if:
- It is not active (is_effectively_active is False), or
- It does not have a related listing in a specific community, or
- It has a listing, but the listing is marked as rejected.

A package version is considered unavailable if:
- The related package is unavailable, or
- The package version itself is not active.
- (If both conditions apply, the package's status takes precedence.)

Additionally, implement unit tests to validate these new functions for
both the Package and PackageVersion models.

Refs. TS-2776
  • Loading branch information
Roffenlund committed Jan 14, 2025
1 parent 4a82877 commit 4d807f5
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 2 deletions.
16 changes: 16 additions & 0 deletions django/thunderstore/repository/models/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ def update_listing(self, has_nsfw_content, categories, community):
listing.categories.add(*categories)
listing.save(update_fields=("has_nsfw_content",))

def listing_is_unavailable(self, listing) -> bool:
if listing is None:
return True

return any([
listing.is_rejected,
listing.is_waiting_for_approval,
])

def is_unavailable(self, community) -> bool:
if self.is_effectively_active is False:
return True

listing = self.get_package_listing(community)
return self.listing_is_unavailable(listing)

@cached_property
def has_wiki(self) -> bool:
try:
Expand Down
6 changes: 6 additions & 0 deletions django/thunderstore/repository/models/package_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ def get_page_url(self, community_identifier: str) -> str:
},
)

def is_unavailable(self, community) -> bool:
unavailable = self.package.is_unavailable(community)
if unavailable:
return True
return self.is_active is False

@cached_property
def display_name(self):
return self.name.replace("_", " ")
Expand Down
74 changes: 72 additions & 2 deletions django/thunderstore/repository/tests/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
from django.core.exceptions import ValidationError

from conftest import TestUserTypes
from thunderstore.community.factories import PackageCategoryFactory, SiteFactory
from thunderstore.community.factories import (
CommunityFactory,
PackageCategoryFactory,
PackageListingFactory,
SiteFactory,
)
from thunderstore.community.models.package_listing import PackageListing
from thunderstore.core.types import UserType
from thunderstore.repository.factories import PackageFactory
from thunderstore.repository.factories import PackageFactory, PackageVersionFactory
from thunderstore.repository.models import (
Namespace,
Package,
Expand All @@ -19,6 +24,7 @@
TeamMemberRole,
)
from thunderstore.wiki.factories import WikiPageFactory
from thunderstore.community.consts import PackageListingReviewStatus

User = get_user_model()

Expand Down Expand Up @@ -224,3 +230,67 @@ def test_package_update_listing(
assert listing.categories.count() == 3
for entry in cats:
assert entry in listing.categories.all()


@pytest.mark.django_db
@pytest.mark.parametrize(
(
"review_status",
"package_is_active",
"require_package_listing_approval",
"expected_is_unavailable_result",
),
[
(PackageListingReviewStatus.approved, True, False, False),
(PackageListingReviewStatus.approved, False, False, True),
(PackageListingReviewStatus.rejected, True, False, True),
(PackageListingReviewStatus.rejected, False, False, True),
(PackageListingReviewStatus.unreviewed, True, True, True),
(PackageListingReviewStatus.unreviewed, True, False, False),
(PackageListingReviewStatus.unreviewed, False, True, True),
(PackageListingReviewStatus.unreviewed, False, False, True),
],
)
def test_package_is_unavailable(
review_status: PackageListingReviewStatus,
package_is_active: bool,
require_package_listing_approval: bool,
expected_is_unavailable_result: bool,
) -> None:
community = CommunityFactory(
require_package_listing_approval=require_package_listing_approval
)

package = PackageFactory(is_active=package_is_active)
if package_is_active:
PackageVersionFactory(package=package, version_number="1.0.0")

PackageListingFactory(
package_=package,
community_=community,
review_status=review_status,
)

assert package.is_unavailable(community) == expected_is_unavailable_result


@pytest.mark.django_db
def test_package_is_unavailable_no_listing() -> None:
community = CommunityFactory()
package = PackageFactory(is_active=True)
PackageVersionFactory(package=package, version_number="1.0.0")

assert package.is_unavailable(community) is True


@pytest.mark.django_db
def test_package_is_unavailable_no_version() -> None:
community = CommunityFactory()
package = PackageFactory(is_active=True)
PackageListingFactory(
package_=package,
community_=community,
review_status=PackageListingReviewStatus.approved,
)

assert package.is_unavailable(community) is True
24 changes: 24 additions & 0 deletions django/thunderstore/repository/tests/test_package_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from thunderstore.repository.factories import PackageFactory, PackageVersionFactory
from thunderstore.repository.models import PackageVersion
from thunderstore.repository.package_formats import PackageFormats
from thunderstore.community.factories import CommunityFactory


@pytest.mark.django_db
Expand Down Expand Up @@ -129,3 +130,26 @@ def test_package_version_is_effectively_active(
version = PackageVersionFactory(package=package, is_active=version_is_active)

assert version.is_effectively_active == (package_is_active and version_is_active)


@pytest.mark.django_db
@pytest.mark.parametrize(
("package_is_unavailable", "version_is_active", "expected_is_unavailable"),
[
(True, True, True),
(True, False, True),
(False, True, False),
(False, False, True),
],
)
def test_package_version_is_unavailable(
package_is_unavailable: bool,
version_is_active: bool,
expected_is_unavailable: bool,
) -> None:
community = CommunityFactory()
package = PackageFactory()
package.is_unavailable = lambda _: package_is_unavailable
version = PackageVersionFactory(package=package, is_active=version_is_active)

assert version.is_unavailable(community) == expected_is_unavailable

0 comments on commit 4d807f5

Please sign in to comment.