1
- use std:: str:: FromStr ;
2
-
3
1
use anyhow:: Result ;
2
+ use uv_client:: { BaseClientBuilder , Connectivity , FlatIndexClient , RegistryClientBuilder } ;
3
+ use uv_dispatch:: BuildDispatch ;
4
+ use uv_distribution:: pyproject_mut:: PyProjectTomlMut ;
5
+ use uv_git:: GitResolver ;
6
+ use uv_requirements:: { NamedRequirementsResolver , RequirementsSource , RequirementsSpecification } ;
7
+ use uv_resolver:: { FlatIndex , InMemoryIndex , OptionsBuilder } ;
8
+ use uv_types:: { BuildIsolation , HashStrategy , InFlight } ;
4
9
5
- use pep508_rs:: Requirement ;
6
10
use uv_cache:: Cache ;
7
- use uv_client:: Connectivity ;
8
- use uv_configuration:: { Concurrency , ExtrasSpecification , PreviewMode } ;
9
- use uv_distribution:: pyproject_mut:: PyProjectTomlMut ;
10
- use uv_distribution:: ProjectWorkspace ;
11
+ use uv_configuration:: { Concurrency , ExtrasSpecification , PreviewMode , SetupPyStrategy } ;
12
+ use uv_distribution:: { DistributionDatabase , ProjectWorkspace } ;
11
13
use uv_warnings:: warn_user;
12
14
15
+ use crate :: commands:: pip:: resolution_environment;
16
+ use crate :: commands:: reporters:: ResolverReporter ;
13
17
use crate :: commands:: { project, ExitStatus } ;
14
18
use crate :: printer:: Printer ;
15
- use crate :: settings:: { InstallerSettings , ResolverSettings } ;
19
+ use crate :: settings:: ResolverInstallerSettings ;
16
20
17
21
/// Add one or more packages to the project requirements.
18
22
#[ allow( clippy:: too_many_arguments) ]
19
23
pub ( crate ) async fn add (
20
- requirements : Vec < String > ,
24
+ requirements : Vec < RequirementsSource > ,
21
25
python : Option < String > ,
26
+ settings : ResolverInstallerSettings ,
22
27
preview : PreviewMode ,
23
28
connectivity : Connectivity ,
24
29
concurrency : Concurrency ,
@@ -33,10 +38,92 @@ pub(crate) async fn add(
33
38
// Find the project requirements.
34
39
let project = ProjectWorkspace :: discover ( & std:: env:: current_dir ( ) ?, None ) . await ?;
35
40
41
+ // Discover or create the virtual environment.
42
+ let venv = project:: init_environment ( project. workspace ( ) , python. as_deref ( ) , cache, printer) ?;
43
+
44
+ let client_builder = BaseClientBuilder :: new ( )
45
+ . connectivity ( connectivity)
46
+ . native_tls ( native_tls)
47
+ . keyring ( settings. keyring_provider ) ;
48
+
49
+ // Read the requirements.
50
+ let RequirementsSpecification { requirements, .. } =
51
+ RequirementsSpecification :: from_sources ( & requirements, & [ ] , & [ ] , & client_builder) . await ?;
52
+
53
+ // TODO(charlie): These are all default values. We should consider whether we want to make them
54
+ // optional on the downstream APIs.
55
+ let python_version = None ;
56
+ let python_platform = None ;
57
+ let hasher = HashStrategy :: default ( ) ;
58
+ let setup_py = SetupPyStrategy :: default ( ) ;
59
+ let build_isolation = BuildIsolation :: default ( ) ;
60
+
61
+ // Determine the environment for the resolution.
62
+ let ( tags, markers) =
63
+ resolution_environment ( python_version, python_platform, venv. interpreter ( ) ) ?;
64
+
65
+ // Initialize the registry client.
66
+ let client = RegistryClientBuilder :: new ( cache. clone ( ) )
67
+ . native_tls ( native_tls)
68
+ . connectivity ( connectivity)
69
+ . index_urls ( settings. index_locations . index_urls ( ) )
70
+ . index_strategy ( settings. index_strategy )
71
+ . keyring ( settings. keyring_provider )
72
+ . markers ( & markers)
73
+ . platform ( venv. interpreter ( ) . platform ( ) )
74
+ . build ( ) ;
75
+
76
+ // Initialize any shared state.
77
+ let git = GitResolver :: default ( ) ;
78
+ let in_flight = InFlight :: default ( ) ;
79
+ let index = InMemoryIndex :: default ( ) ;
80
+
81
+ // Resolve the flat indexes from `--find-links`.
82
+ let flat_index = {
83
+ let client = FlatIndexClient :: new ( & client, cache) ;
84
+ let entries = client. fetch ( settings. index_locations . flat_index ( ) ) . await ?;
85
+ FlatIndex :: from_entries ( entries, Some ( & tags) , & hasher, & settings. build_options )
86
+ } ;
87
+
88
+ // Create a build dispatch.
89
+ let build_dispatch = BuildDispatch :: new (
90
+ & client,
91
+ cache,
92
+ venv. interpreter ( ) ,
93
+ & settings. index_locations ,
94
+ & flat_index,
95
+ & index,
96
+ & git,
97
+ & in_flight,
98
+ setup_py,
99
+ & settings. config_setting ,
100
+ build_isolation,
101
+ settings. link_mode ,
102
+ & settings. build_options ,
103
+ concurrency,
104
+ preview,
105
+ )
106
+ . with_options (
107
+ OptionsBuilder :: new ( )
108
+ . exclude_newer ( settings. exclude_newer )
109
+ . build ( ) ,
110
+ ) ;
111
+
112
+ // Resolve any unnamed requirements.
113
+ let requirements = NamedRequirementsResolver :: new (
114
+ requirements,
115
+ & hasher,
116
+ & index,
117
+ DistributionDatabase :: new ( & client, & build_dispatch, concurrency. downloads , preview) ,
118
+ )
119
+ . with_reporter ( ResolverReporter :: from ( printer) )
120
+ . resolve ( )
121
+ . await ?;
122
+
123
+ // Add the requirements to the `pyproject.toml`.
36
124
let mut pyproject = PyProjectTomlMut :: from_toml ( project. current_project ( ) . pyproject_toml ( ) ) ?;
37
125
for req in requirements {
38
- let req = Requirement :: from_str ( & req) ?;
39
- pyproject. add_dependency ( & req) ?;
126
+ pyproject. add_dependency ( & pep508_rs:: Requirement :: from ( req) ) ?;
40
127
}
41
128
42
129
// Save the modified `pyproject.toml`.
@@ -45,12 +132,6 @@ pub(crate) async fn add(
45
132
pyproject. to_string ( ) ,
46
133
) ?;
47
134
48
- // Discover or create the virtual environment.
49
- let venv = project:: init_environment ( project. workspace ( ) , python. as_deref ( ) , cache, printer) ?;
50
-
51
- // Use the default settings.
52
- let settings = ResolverSettings :: default ( ) ;
53
-
54
135
// Lock and sync the environment.
55
136
let lock = project:: lock:: do_lock (
56
137
project. workspace ( ) ,
@@ -76,7 +157,6 @@ pub(crate) async fn add(
76
157
77
158
// Perform a full sync, because we don't know what exactly is affected by the removal.
78
159
// TODO(ibraheem): Should we accept CLI overrides for this? Should we even sync here?
79
- let settings = InstallerSettings :: default ( ) ;
80
160
let extras = ExtrasSpecification :: All ;
81
161
let dev = true ;
82
162
0 commit comments