@@ -54,7 +54,12 @@ class AddCommand(InstallerCommand, InitCommand):
54
54
flag = False ,
55
55
multiple = True ,
56
56
),
57
- option ("optional" , None , "Add as an optional dependency." ),
57
+ option (
58
+ "optional" ,
59
+ None ,
60
+ "Add as an optional dependency to an extra." ,
61
+ flag = False ,
62
+ ),
58
63
option (
59
64
"python" ,
60
65
None ,
@@ -137,6 +142,10 @@ def handle(self) -> int:
137
142
"You can only specify one package when using the --extras option"
138
143
)
139
144
145
+ optional = self .option ("optional" )
146
+ if optional and group != MAIN_GROUP :
147
+ raise ValueError ("You can only add optional dependencies to the main group" )
148
+
140
149
# tomlkit types are awkward to work with, treat content as a mostly untyped
141
150
# dictionary.
142
151
content : dict [str , Any ] = self .poetry .file .read ()
@@ -156,13 +165,19 @@ def handle(self) -> int:
156
165
or "optional-dependencies" in project_content
157
166
):
158
167
use_project_section = True
168
+ if optional :
169
+ project_section = project_content .get (
170
+ "optional-dependencies" , {}
171
+ ).get (optional , array ())
172
+ else :
173
+ project_section = project_content .get ("dependencies" , array ())
159
174
project_dependency_names = [
160
- Dependency .create_from_pep_508 (dep ).name
161
- for dep in project_content .get ("dependencies" , {})
175
+ Dependency .create_from_pep_508 (dep ).name for dep in project_section
162
176
]
177
+ else :
178
+ project_section = array ()
163
179
164
180
poetry_section = poetry_content .get ("dependencies" , table ())
165
- project_section = project_content .get ("dependencies" , array ())
166
181
else :
167
182
if "group" not in poetry_content :
168
183
poetry_content ["group" ] = table (is_super_table = True )
@@ -194,6 +209,13 @@ def handle(self) -> int:
194
209
self .line ("Nothing to add." )
195
210
return 0
196
211
212
+ if optional and not use_project_section :
213
+ self .line_error (
214
+ "<warning>Optional dependencies will not be added to extras"
215
+ " in legacy mode. Consider converting your project to use the [project]"
216
+ " section.</warning>"
217
+ )
218
+
197
219
requirements = self ._determine_requirements (
198
220
packages ,
199
221
allow_prereleases = self .option ("allow-prereleases" ),
@@ -214,7 +236,7 @@ def handle(self) -> int:
214
236
215
237
constraint [key ] = value
216
238
217
- if self . option ( " optional" ) :
239
+ if optional :
218
240
constraint ["optional" ] = True
219
241
220
242
if self .option ("allow-prereleases" ):
@@ -290,7 +312,7 @@ def handle(self) -> int:
290
312
# that cannot be stored in the project section
291
313
poetry_constraint : dict [str , Any ] = inline_table ()
292
314
if not isinstance (constraint , str ):
293
- for key in ["optional" , " allow-prereleases" , "develop" , "source" ]:
315
+ for key in ["allow-prereleases" , "develop" , "source" ]:
294
316
if value := constraint .get (key ):
295
317
poetry_constraint [key ] = value
296
318
if poetry_constraint :
@@ -310,9 +332,15 @@ def handle(self) -> int:
310
332
poetry_section [constraint_name ] = poetry_constraint
311
333
312
334
# Refresh the locker
313
- if project_section and "dependencies" not in project_content :
335
+ if project_section :
314
336
assert group == MAIN_GROUP
315
- project_content ["dependencies" ] = project_section
337
+ if optional :
338
+ if "optional-dependencies" not in project_content :
339
+ project_content ["optional-dependencies" ] = table ()
340
+ if optional not in project_content ["optional-dependencies" ]:
341
+ project_content ["optional-dependencies" ][optional ] = project_section
342
+ elif "dependencies" not in project_content :
343
+ project_content ["dependencies" ] = project_section
316
344
if poetry_section :
317
345
if "tool" not in content :
318
346
content ["tool" ] = table ()
0 commit comments