@@ -31,7 +31,7 @@ use pypi_types::{
3131 redact_git_credentials, HashDigest , ParsedArchiveUrl , ParsedGitUrl , Requirement ,
3232 RequirementSource , ResolverMarkerEnvironment ,
3333} ;
34- use uv_configuration:: ExtrasSpecification ;
34+ use uv_configuration:: { BuildOptions , ExtrasSpecification } ;
3535use uv_distribution:: DistributionDatabase ;
3636use uv_fs:: { relative_to, PortablePath , PortablePathBuf } ;
3737use uv_git:: { GitReference , GitSha , RepositoryReference , ResolvedRepositoryReference } ;
@@ -561,6 +561,7 @@ impl Lock {
561561 tags : & Tags ,
562562 extras : & ExtrasSpecification ,
563563 dev : & [ GroupName ] ,
564+ build_options : & BuildOptions ,
564565 ) -> Result < Resolution , LockError > {
565566 let mut queue: VecDeque < ( & Package , Option < & ExtraName > ) > = VecDeque :: new ( ) ;
566567 let mut seen = FxHashSet :: default ( ) ;
@@ -649,7 +650,11 @@ impl Lock {
649650 }
650651 map. insert (
651652 dist. id . name . clone ( ) ,
652- ResolvedDist :: Installable ( dist. to_dist ( project. workspace ( ) . install_path ( ) , tags) ?) ,
653+ ResolvedDist :: Installable ( dist. to_dist (
654+ project. workspace ( ) . install_path ( ) ,
655+ tags,
656+ build_options,
657+ ) ?) ,
653658 ) ;
654659 hashes. insert ( dist. id . name . clone ( ) , dist. hashes ( ) ) ;
655660 }
@@ -876,6 +881,7 @@ impl Lock {
876881 constraints : & [ Requirement ] ,
877882 overrides : & [ Requirement ] ,
878883 indexes : Option < & IndexLocations > ,
884+ build_options : & BuildOptions ,
879885 tags : & Tags ,
880886 database : & DistributionDatabase < ' _ , Context > ,
881887 ) -> Result < SatisfiesResult < ' _ > , LockError > {
@@ -1066,7 +1072,7 @@ impl Lock {
10661072 }
10671073
10681074 // Get the metadata for the distribution.
1069- let dist = package. to_dist ( workspace. install_path ( ) , tags) ?;
1075+ let dist = package. to_dist ( workspace. install_path ( ) , tags, build_options ) ?;
10701076
10711077 let Ok ( archive) = database
10721078 . get_or_build_wheel_metadata ( & dist, HashPolicy :: None )
@@ -1565,78 +1571,106 @@ impl Package {
15651571 }
15661572
15671573 /// Convert the [`Package`] to a [`Dist`] that can be used in installation.
1568- fn to_dist ( & self , workspace_root : & Path , tags : & Tags ) -> Result < Dist , LockError > {
1569- if let Some ( best_wheel_index) = self . find_best_wheel ( tags) {
1570- return match & self . id . source {
1571- Source :: Registry ( source) => {
1572- let wheels = self
1573- . wheels
1574- . iter ( )
1575- . map ( |wheel| wheel. to_registry_dist ( source, workspace_root) )
1576- . collect :: < Result < _ , LockError > > ( ) ?;
1577- let reg_built_dist = RegistryBuiltDist {
1578- wheels,
1579- best_wheel_index,
1580- sdist : None ,
1581- } ;
1582- Ok ( Dist :: Built ( BuiltDist :: Registry ( reg_built_dist) ) )
1583- }
1584- Source :: Path ( path) => {
1585- let filename: WheelFilename = self . wheels [ best_wheel_index] . filename . clone ( ) ;
1586- let path_dist = PathBuiltDist {
1587- filename,
1588- url : verbatim_url ( workspace_root. join ( path) , & self . id ) ?,
1589- install_path : workspace_root. join ( path) ,
1590- } ;
1591- let built_dist = BuiltDist :: Path ( path_dist) ;
1592- Ok ( Dist :: Built ( built_dist) )
1593- }
1594- Source :: Direct ( url, direct) => {
1595- let filename: WheelFilename = self . wheels [ best_wheel_index] . filename . clone ( ) ;
1596- let url = Url :: from ( ParsedArchiveUrl {
1597- url : url. to_url ( ) ,
1598- subdirectory : direct. subdirectory . as_ref ( ) . map ( PathBuf :: from) ,
1599- ext : DistExtension :: Wheel ,
1600- } ) ;
1601- let direct_dist = DirectUrlBuiltDist {
1602- filename,
1603- location : url. clone ( ) ,
1604- url : VerbatimUrl :: from_url ( url) ,
1605- } ;
1606- let built_dist = BuiltDist :: DirectUrl ( direct_dist) ;
1607- Ok ( Dist :: Built ( built_dist) )
1608- }
1609- Source :: Git ( _, _) => Err ( LockErrorKind :: InvalidWheelSource {
1610- id : self . id . clone ( ) ,
1611- source_type : "Git" ,
1612- }
1613- . into ( ) ) ,
1614- Source :: Directory ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1615- id : self . id . clone ( ) ,
1616- source_type : "directory" ,
1617- }
1618- . into ( ) ) ,
1619- Source :: Editable ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1620- id : self . id . clone ( ) ,
1621- source_type : "editable" ,
1622- }
1623- . into ( ) ) ,
1624- Source :: Virtual ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1625- id : self . id . clone ( ) ,
1626- source_type : "virtual" ,
1627- }
1628- . into ( ) ) ,
1574+ fn to_dist (
1575+ & self ,
1576+ workspace_root : & Path ,
1577+ tags : & Tags ,
1578+ build_options : & BuildOptions ,
1579+ ) -> Result < Dist , LockError > {
1580+ let no_binary = build_options. no_binary_package ( & self . id . name ) ;
1581+ let no_build = build_options. no_build_package ( & self . id . name ) ;
1582+
1583+ if !no_binary {
1584+ if let Some ( best_wheel_index) = self . find_best_wheel ( tags) {
1585+ return match & self . id . source {
1586+ Source :: Registry ( source) => {
1587+ let wheels = self
1588+ . wheels
1589+ . iter ( )
1590+ . map ( |wheel| wheel. to_registry_dist ( source, workspace_root) )
1591+ . collect :: < Result < _ , LockError > > ( ) ?;
1592+ let reg_built_dist = RegistryBuiltDist {
1593+ wheels,
1594+ best_wheel_index,
1595+ sdist : None ,
1596+ } ;
1597+ Ok ( Dist :: Built ( BuiltDist :: Registry ( reg_built_dist) ) )
1598+ }
1599+ Source :: Path ( path) => {
1600+ let filename: WheelFilename =
1601+ self . wheels [ best_wheel_index] . filename . clone ( ) ;
1602+ let path_dist = PathBuiltDist {
1603+ filename,
1604+ url : verbatim_url ( workspace_root. join ( path) , & self . id ) ?,
1605+ install_path : workspace_root. join ( path) ,
1606+ } ;
1607+ let built_dist = BuiltDist :: Path ( path_dist) ;
1608+ Ok ( Dist :: Built ( built_dist) )
1609+ }
1610+ Source :: Direct ( url, direct) => {
1611+ let filename: WheelFilename =
1612+ self . wheels [ best_wheel_index] . filename . clone ( ) ;
1613+ let url = Url :: from ( ParsedArchiveUrl {
1614+ url : url. to_url ( ) ,
1615+ subdirectory : direct. subdirectory . as_ref ( ) . map ( PathBuf :: from) ,
1616+ ext : DistExtension :: Wheel ,
1617+ } ) ;
1618+ let direct_dist = DirectUrlBuiltDist {
1619+ filename,
1620+ location : url. clone ( ) ,
1621+ url : VerbatimUrl :: from_url ( url) ,
1622+ } ;
1623+ let built_dist = BuiltDist :: DirectUrl ( direct_dist) ;
1624+ Ok ( Dist :: Built ( built_dist) )
1625+ }
1626+ Source :: Git ( _, _) => Err ( LockErrorKind :: InvalidWheelSource {
1627+ id : self . id . clone ( ) ,
1628+ source_type : "Git" ,
1629+ }
1630+ . into ( ) ) ,
1631+ Source :: Directory ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1632+ id : self . id . clone ( ) ,
1633+ source_type : "directory" ,
1634+ }
1635+ . into ( ) ) ,
1636+ Source :: Editable ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1637+ id : self . id . clone ( ) ,
1638+ source_type : "editable" ,
1639+ }
1640+ . into ( ) ) ,
1641+ Source :: Virtual ( _) => Err ( LockErrorKind :: InvalidWheelSource {
1642+ id : self . id . clone ( ) ,
1643+ source_type : "virtual" ,
1644+ }
1645+ . into ( ) ) ,
1646+ } ;
16291647 } ;
1630- } ;
1648+ }
16311649
1632- if let Some ( sdist) = self . to_source_dist ( workspace_root) ? {
1633- return Ok ( Dist :: Source ( sdist) ) ;
1650+ if !no_build {
1651+ if let Some ( sdist) = self . to_source_dist ( workspace_root) ? {
1652+ return Ok ( Dist :: Source ( sdist) ) ;
1653+ }
16341654 }
16351655
1636- Err ( LockErrorKind :: NeitherSourceDistNorWheel {
1637- id : self . id . clone ( ) ,
1656+ match ( no_binary, no_build) {
1657+ ( true , true ) => Err ( LockErrorKind :: NoBinaryNoBuild {
1658+ id : self . id . clone ( ) ,
1659+ }
1660+ . into ( ) ) ,
1661+ ( true , false ) => Err ( LockErrorKind :: NoBinary {
1662+ id : self . id . clone ( ) ,
1663+ }
1664+ . into ( ) ) ,
1665+ ( false , true ) => Err ( LockErrorKind :: NoBuild {
1666+ id : self . id . clone ( ) ,
1667+ }
1668+ . into ( ) ) ,
1669+ ( false , false ) => Err ( LockErrorKind :: NeitherSourceDistNorWheel {
1670+ id : self . id . clone ( ) ,
1671+ }
1672+ . into ( ) ) ,
16381673 }
1639- . into ( ) )
16401674 }
16411675
16421676 /// Convert the source of this [`Package`] to a [`SourceDist`] that can be used in installation.
@@ -3758,6 +3792,26 @@ enum LockErrorKind {
37583792 /// The ID of the distribution that has a missing base.
37593793 id : PackageId ,
37603794 } ,
3795+ /// An error that occurs when a distribution is marked as both `--no-binary` and `--no-build`.
3796+ #[ error( "distribution {id} can't be installed because it is marked as both `--no-binary` and `--no-build`" ) ]
3797+ NoBinaryNoBuild {
3798+ /// The ID of the distribution.
3799+ id : PackageId ,
3800+ } ,
3801+ /// An error that occurs when a distribution is marked as both `--no-binary`, but no source
3802+ /// distribution is available.
3803+ #[ error( "distribution {id} can't be installed because it is marked as `--no-binary` but has no source distribution" ) ]
3804+ NoBinary {
3805+ /// The ID of the distribution.
3806+ id : PackageId ,
3807+ } ,
3808+ /// An error that occurs when a distribution is marked as both `--no-build`, but no binary
3809+ /// distribution is available.
3810+ #[ error( "distribution {id} can't be installed because it is marked as `--no-build` but has no binary distribution" ) ]
3811+ NoBuild {
3812+ /// The ID of the distribution.
3813+ id : PackageId ,
3814+ } ,
37613815 /// An error that occurs when converting between URLs and paths.
37623816 #[ error( "found dependency `{id}` with no locked distribution" ) ]
37633817 VerbatimUrl {
0 commit comments