11from __future__ import annotations
22
3+ import logging
4+ import os
5+ from importlib import metadata
36from typing import TYPE_CHECKING
47
8+ from packaging .utils import canonicalize_name
9+
10+ from variantlib .constants import VARIANT_ABI_DEPENDENCY_NAMESPACE
511from variantlib .models .variant import VariantDescription
612from variantlib .models .variant import VariantFeature
713from variantlib .models .variant import VariantProperty
2026 from variantlib .protocols import VariantFeatureValue
2127 from variantlib .protocols import VariantNamespace
2228
29+ logger = logging .getLogger (__name__ )
30+
31+
32+ def _normalize_package_name (name : str ) -> str :
33+ # VALIDATION_FEATURE_NAME_REGEX does not accepts "-"
34+ return canonicalize_name (name ).replace ("-" , "_" )
35+
36+
37+ def _normalize_package_version (version : str ) -> str :
38+ # VALIDATION_VALUE_REGEX does not accepts "+"
39+ return version .split ("+" , maxsplit = 1 )[0 ]
40+
2341
2442def filter_variants (
2543 vdescs : list [VariantDescription ],
@@ -124,8 +142,62 @@ def sort_and_filter_supported_variants(
124142 :param property_priorities: Ordered list of `VariantProperty` objects.
125143 :return: Sorted and filtered list of `VariantDescription` objects.
126144 """
145+
127146 validate_type (vdescs , list [VariantDescription ])
147+ validate_type (supported_vprops , list [VariantProperty ])
128148
149+ if namespace_priorities is None :
150+ namespace_priorities = []
151+
152+ # ======================================================================= #
153+ # ABI DEPENDENCY INJECTION #
154+ # ======================================================================= #
155+
156+ # 1. Manually fed from environment variable
157+ # Note: come first for "implicit higher priority"
158+ # Env Var Format: `VARIANT_ABI_DEPENDENCY=packageA==1.2.3,...,packageZ==7.8.9`
159+ if variant_abi_deps_env := os .environ .get ("NV_VARIANT_PROVIDER_FORCE_SM_ARCH" ):
160+ for pkg_spec in variant_abi_deps_env .split ("," ):
161+ try :
162+ pkg_name , pkg_version = pkg_spec .split ("==" , maxsplit = 1 )
163+ except ValueError :
164+ logger .exception (
165+ "`NV_VARIANT_PROVIDER_FORCE_SM_ARCH` received an invalid value "
166+ "`%(pkg_spec)s`. It will be ignored.\n "
167+ "Expected format: `packageA==1.2.3,...,packageZ==7.8.9`." ,
168+ {"pkg_spec" : pkg_spec },
169+ )
170+ continue
171+
172+ supported_vprops .append (
173+ VariantProperty (
174+ namespace = VARIANT_ABI_DEPENDENCY_NAMESPACE ,
175+ feature = _normalize_package_name (pkg_name ),
176+ value = _normalize_package_version (pkg_version ),
177+ )
178+ )
179+
180+ # 2. Automatically populate from the current python environment
181+ packages = [
182+ (dist .metadata ["Name" ], dist .version ) for dist in metadata .distributions ()
183+ ]
184+ for pkg_name , pkg_version in sorted (packages ):
185+ supported_vprops .append (
186+ VariantProperty (
187+ namespace = VARIANT_ABI_DEPENDENCY_NAMESPACE ,
188+ feature = _normalize_package_name (pkg_name ),
189+ value = _normalize_package_version (pkg_version ),
190+ )
191+ )
192+
193+ # 3. Adding `VARIANT_ABI_DEPENDENCY_NAMESPACE` at the back of`namespace_priorities`
194+ namespace_priorities .append (VARIANT_ABI_DEPENDENCY_NAMESPACE )
195+
196+ # ======================================================================= #
197+ # NULL VARIANT #
198+ # ======================================================================= #
199+
200+ # Adding the `null-variant` to the list - always "compatible"
129201 if (null_variant := VariantDescription ()) not in vdescs :
130202 """Add a null variant description to the list."""
131203 # This is needed to ensure that we always consider the null variant
@@ -139,7 +211,9 @@ def sort_and_filter_supported_variants(
139211 """No supported properties provided, return no variants."""
140212 return []
141213
142- validate_type (supported_vprops , list [VariantProperty ])
214+ # ======================================================================= #
215+ # FILTERING #
216+ # ======================================================================= #
143217
144218 # Step 1: we remove any duplicate, or unsupported `VariantDescription` on
145219 # this platform.
@@ -153,6 +227,10 @@ def sort_and_filter_supported_variants(
153227 )
154228 )
155229
230+ # ======================================================================= #
231+ # SORTING #
232+ # ======================================================================= #
233+
156234 # Step 2: we sort the supported `VariantProperty`s based on their respective
157235 # priority.
158236 sorted_supported_vprops = sort_variant_properties (
0 commit comments