From f933112abdb9a313798ff243b9d4fce55f9d3ef5 Mon Sep 17 00:00:00 2001 From: Andrey Cheptsov Date: Thu, 5 Mar 2026 12:46:22 +0100 Subject: [PATCH 1/3] Update VastAI community_cloud to include server and community offers. Keep server-only behavior when disabled, and add tests for the new default and enabled filter semantics. Made-with: Cursor --- src/gpuhunt/providers/vastai.py | 24 +++++++++++++++++++++--- src/tests/providers/test_vastai.py | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/tests/providers/test_vastai.py diff --git a/src/gpuhunt/providers/vastai.py b/src/gpuhunt/providers/vastai.py index 19ab367..a49b02b 100644 --- a/src/gpuhunt/providers/vastai.py +++ b/src/gpuhunt/providers/vastai.py @@ -21,13 +21,20 @@ class VastAIProvider(AbstractProvider): NAME = "vastai" - def __init__(self, extra_filters: Optional[dict[str, dict[Operators, FilterValue]]] = None): + def __init__( + self, + extra_filters: Optional[dict[str, dict[Operators, FilterValue]]] = None, + community_cloud: bool = False, + ): self.extra_filters = extra_filters + self.community_cloud = community_cloud def get( self, query_filter: Optional[QueryFilter] = None, balance_resources: bool = True ) -> list[RawCatalogItem]: - filters: dict[str, Any] = self.make_filters(query_filter or QueryFilter()) + filters: dict[str, Any] = self.make_filters( + query_filter or QueryFilter(), community_cloud=self.community_cloud + ) if self.extra_filters: for key, constraints in self.extra_filters.items(): for op, value in constraints.items(): @@ -79,7 +86,9 @@ def get( return instance_offers @staticmethod - def make_filters(q: QueryFilter) -> dict[str, dict[Operators, FilterValue]]: + def make_filters( + q: QueryFilter, community_cloud: bool = False + ) -> dict[str, dict[Operators, FilterValue]]: filters = defaultdict(dict) if q.min_cpu is not None: filters["cpu_cores"]["gte"] = q.min_cpu @@ -120,6 +129,11 @@ def make_filters(q: QueryFilter) -> dict[str, dict[Operators, FilterValue]]: filters["compute_capability"]["gte"] = compute_cap(q.min_compute_capability) if q.max_compute_capability is not None: filters["compute_capability"]["lte"] = compute_cap(q.max_compute_capability) + # Datacenter offers map to Vast's "server cloud" scope. + # When community_cloud is enabled, keep scope unfiltered so both + # server and community offers are returned. + if not community_cloud: + filters["datacenter"]["eq"] = True filters["rentable"]["eq"] = True filters["rented"]["eq"] = False filters["order"] = [["score", "desc"]] @@ -128,6 +142,10 @@ def make_filters(q: QueryFilter) -> dict[str, dict[Operators, FilterValue]]: @staticmethod def satisfies_filters(offer: dict, filters: dict[str, dict[Operators, FilterValue]]) -> bool: for key in filters: + # `datacenter`/`external` are query scope controls. + # They don't map to offer fields with strict eq semantics. + if key in {"datacenter", "external"}: + continue if key not in offer: continue for op, value in filters[key].items(): diff --git a/src/tests/providers/test_vastai.py b/src/tests/providers/test_vastai.py new file mode 100644 index 0000000..95ef187 --- /dev/null +++ b/src/tests/providers/test_vastai.py @@ -0,0 +1,15 @@ +from gpuhunt._internal.models import QueryFilter +from gpuhunt.providers.vastai import VastAIProvider + + +def test_make_filters_defaults_to_datacenter_only(): + filters = VastAIProvider.make_filters(QueryFilter()) + assert filters["datacenter"]["eq"] is True + assert "external" not in filters + + +def test_make_filters_does_not_constrain_scope_when_community_cloud_enabled(): + filters = VastAIProvider.make_filters(QueryFilter(), community_cloud=True) + assert "datacenter" not in filters + assert "external" not in filters + From c1c09215fcb1d0be34386dc37e1ad94257f96b95 Mon Sep 17 00:00:00 2001 From: Andrey Cheptsov Date: Thu, 5 Mar 2026 12:53:37 +0100 Subject: [PATCH 2/3] Fix CI lint failure in VastAI provider tests. Made-with: Cursor --- src/tests/providers/test_vastai.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/providers/test_vastai.py b/src/tests/providers/test_vastai.py index 95ef187..5ef16af 100644 --- a/src/tests/providers/test_vastai.py +++ b/src/tests/providers/test_vastai.py @@ -12,4 +12,3 @@ def test_make_filters_does_not_constrain_scope_when_community_cloud_enabled(): filters = VastAIProvider.make_filters(QueryFilter(), community_cloud=True) assert "datacenter" not in filters assert "external" not in filters - From 37419e09efe054a8c7699b7931a25541fe685b5e Mon Sep 17 00:00:00 2001 From: Andrey Cheptsov Date: Thu, 5 Mar 2026 13:50:34 +0100 Subject: [PATCH 3/3] Keep gpuhunt default VastAI scope backward compatible. Default behavior remains server+community offers. Set community_cloud=false to restrict to server cloud only. Made-with: Cursor --- src/gpuhunt/providers/vastai.py | 4 ++-- src/tests/providers/test_vastai.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gpuhunt/providers/vastai.py b/src/gpuhunt/providers/vastai.py index a49b02b..8469f7e 100644 --- a/src/gpuhunt/providers/vastai.py +++ b/src/gpuhunt/providers/vastai.py @@ -24,7 +24,7 @@ class VastAIProvider(AbstractProvider): def __init__( self, extra_filters: Optional[dict[str, dict[Operators, FilterValue]]] = None, - community_cloud: bool = False, + community_cloud: bool = True, ): self.extra_filters = extra_filters self.community_cloud = community_cloud @@ -87,7 +87,7 @@ def get( @staticmethod def make_filters( - q: QueryFilter, community_cloud: bool = False + q: QueryFilter, community_cloud: bool = True ) -> dict[str, dict[Operators, FilterValue]]: filters = defaultdict(dict) if q.min_cpu is not None: diff --git a/src/tests/providers/test_vastai.py b/src/tests/providers/test_vastai.py index 5ef16af..ffb5f7c 100644 --- a/src/tests/providers/test_vastai.py +++ b/src/tests/providers/test_vastai.py @@ -3,7 +3,7 @@ def test_make_filters_defaults_to_datacenter_only(): - filters = VastAIProvider.make_filters(QueryFilter()) + filters = VastAIProvider.make_filters(QueryFilter(), community_cloud=False) assert filters["datacenter"]["eq"] is True assert "external" not in filters