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 ],
@@ -125,7 +143,60 @@ def sort_and_filter_supported_variants(
125143 :return: Sorted and filtered list of `VariantDescription` objects.
126144 """
127145 validate_type (vdescs , list [VariantDescription ])
146+ validate_type (supported_vprops , list [VariantProperty ])
128147
148+ if namespace_priorities is None :
149+ namespace_priorities = []
150+
151+ # ======================================================================= #
152+ # ABI DEPENDENCY ADDITION #
153+ # ======================================================================= #
154+
155+ # A. Adding ABI Dependencies Marks
156+ # A.1. From the current environment
157+ packages = [
158+ (dist .metadata ["Name" ], dist .version ) for dist in metadata .distributions ()
159+ ]
160+ for pkg_name , pkg_version in sorted (packages ):
161+ supported_vprops .append (
162+ VariantProperty (
163+ namespace = VARIANT_ABI_DEPENDENCY_NAMESPACE ,
164+ feature = _normalize_package_name (pkg_name ),
165+ value = _normalize_package_version (pkg_version ),
166+ )
167+ )
168+
169+ # A.2. Manually fed from environment variable
170+ # Format `VARIANT_ABI_DEPENDENCY=packageA==1.2.3,...,packageZ==7.8.9`
171+ if variant_abi_deps_env := os .environ .get ("NV_VARIANT_PROVIDER_FORCE_SM_ARCH" ):
172+ for pkg_spec in variant_abi_deps_env .split ("," ):
173+ try :
174+ pkg_name , pkg_version = pkg_spec .split ("==" , maxsplit = 1 )
175+ except ValueError :
176+ logger .exception (
177+ "`NV_VARIANT_PROVIDER_FORCE_SM_ARCH` received an invalid value "
178+ "`%(pkg_spec)s`. It will be ignored.\n "
179+ "Expected format: `packageA==1.2.3,...,packageZ==7.8.9`." ,
180+ {"pkg_spec" : pkg_spec },
181+ )
182+ continue
183+
184+ supported_vprops .append (
185+ VariantProperty (
186+ namespace = VARIANT_ABI_DEPENDENCY_NAMESPACE ,
187+ feature = _normalize_package_name (pkg_name ),
188+ value = _normalize_package_version (pkg_version ),
189+ )
190+ )
191+
192+ # A.3 Adding `VARIANT_ABI_DEPENDENCY_NAMESPACE` at the back of`namespace_priorities`
193+ namespace_priorities .append (VARIANT_ABI_DEPENDENCY_NAMESPACE )
194+
195+ # ======================================================================= #
196+ # NULL VARIANT #
197+ # ======================================================================= #
198+
199+ # B. Adding the `null-variant` to the list - always "compatible"
129200 if (null_variant := VariantDescription ()) not in vdescs :
130201 """Add a null variant description to the list."""
131202 # This is needed to ensure that we always consider the null variant
@@ -139,8 +210,6 @@ def sort_and_filter_supported_variants(
139210 """No supported properties provided, return no variants."""
140211 return []
141212
142- validate_type (supported_vprops , list [VariantProperty ])
143-
144213 # Step 1: we remove any duplicate, or unsupported `VariantDescription` on
145214 # this platform.
146215 filtered_vdescs = list (
0 commit comments