1
1
from __future__ import annotations
2
2
3
+ from contextlib import suppress
3
4
from pathlib import Path
4
5
from typing import TYPE_CHECKING
5
6
from typing import Any
@@ -69,13 +70,6 @@ def __init__(self) -> None:
69
70
def handle (self ) -> int :
70
71
from pathlib import Path
71
72
72
- from poetry .core .vcs .git import GitConfig
73
-
74
- from poetry .config .config import Config
75
- from poetry .layouts import layout
76
- from poetry .pyproject .toml import PyProjectTOML
77
- from poetry .utils .env import EnvManager
78
-
79
73
project_path = Path .cwd ()
80
74
81
75
if self .io .input .option ("directory" ):
@@ -86,6 +80,24 @@ def handle(self) -> int:
86
80
)
87
81
return 1
88
82
83
+ return self ._init_pyproject (project_path = project_path )
84
+
85
+ def _init_pyproject (
86
+ self ,
87
+ project_path : Path ,
88
+ allow_interactive : bool = True ,
89
+ layout_name : str = "standard" ,
90
+ readme_format : str = "md" ,
91
+ ) -> int :
92
+ from poetry .core .vcs .git import GitConfig
93
+
94
+ from poetry .config .config import Config
95
+ from poetry .layouts import layout
96
+ from poetry .pyproject .toml import PyProjectTOML
97
+ from poetry .utils .env import EnvManager
98
+
99
+ is_interactive = self .io .is_interactive () and allow_interactive
100
+
89
101
pyproject = PyProjectTOML (project_path / "pyproject.toml" )
90
102
91
103
if pyproject .file .exists ():
@@ -105,7 +117,7 @@ def handle(self) -> int:
105
117
106
118
vcs_config = GitConfig ()
107
119
108
- if self . io . is_interactive () :
120
+ if is_interactive :
109
121
self .line ("" )
110
122
self .line (
111
123
"This command will guide you through creating your"
@@ -115,21 +127,24 @@ def handle(self) -> int:
115
127
116
128
name = self .option ("name" )
117
129
if not name :
118
- name = Path . cwd () .name .lower ()
130
+ name = project_path .name .lower ()
119
131
120
- question = self .create_question (
121
- f"Package name [<comment>{ name } </comment>]: " , default = name
122
- )
123
- name = self .ask (question )
132
+ if is_interactive :
133
+ question = self .create_question (
134
+ f"Package name [<comment>{ name } </comment>]: " , default = name
135
+ )
136
+ name = self .ask (question )
124
137
125
138
version = "0.1.0"
126
- question = self .create_question (
127
- f"Version [<comment>{ version } </comment>]: " , default = version
128
- )
129
- version = self .ask (question )
130
139
131
- description = self .option ("description" )
132
- if not description :
140
+ if is_interactive :
141
+ question = self .create_question (
142
+ f"Version [<comment>{ version } </comment>]: " , default = version
143
+ )
144
+ version = self .ask (question )
145
+
146
+ description = self .option ("description" ) or ""
147
+ if not description and is_interactive :
133
148
description = self .ask (self .create_question ("Description []: " , default = "" ))
134
149
135
150
author = self .option ("author" )
@@ -139,22 +154,23 @@ def handle(self) -> int:
139
154
if author_email :
140
155
author += f" <{ author_email } >"
141
156
142
- question = self .create_question (
143
- f"Author [<comment>{ author } </comment>, n to skip]: " , default = author
144
- )
145
- question .set_validator (lambda v : self ._validate_author (v , author ))
146
- author = self .ask (question )
157
+ if is_interactive :
158
+ question = self .create_question (
159
+ f"Author [<comment>{ author } </comment>, n to skip]: " , default = author
160
+ )
161
+ question .set_validator (lambda v : self ._validate_author (v , author ))
162
+ author = self .ask (question )
147
163
148
164
authors = [author ] if author else []
149
165
150
- license = self .option ("license" )
151
- if not license :
152
- license = self .ask (self .create_question ("License []: " , default = "" ))
166
+ license_name = self .option ("license" )
167
+ if not license_name and is_interactive :
168
+ license_name = self .ask (self .create_question ("License []: " , default = "" ))
153
169
154
170
python = self .option ("python" )
155
171
if not python :
156
172
config = Config .create ()
157
- default_python = (
173
+ python = (
158
174
"^"
159
175
+ EnvManager .get_python_version (
160
176
precision = 2 ,
@@ -163,13 +179,14 @@ def handle(self) -> int:
163
179
).to_string ()
164
180
)
165
181
166
- question = self .create_question (
167
- f"Compatible Python versions [<comment>{ default_python } </comment>]: " ,
168
- default = default_python ,
169
- )
170
- python = self .ask (question )
182
+ if is_interactive :
183
+ question = self .create_question (
184
+ f"Compatible Python versions [<comment>{ python } </comment>]: " ,
185
+ default = python ,
186
+ )
187
+ python = self .ask (question )
171
188
172
- if self . io . is_interactive () :
189
+ if is_interactive :
173
190
self .line ("" )
174
191
175
192
requirements : Requirements = {}
@@ -180,27 +197,25 @@ def handle(self) -> int:
180
197
181
198
question_text = "Would you like to define your main dependencies interactively?"
182
199
help_message = """\
183
- You can specify a package in the following forms:
184
- - A single name (<b>requests</b>): this will search for matches on PyPI
185
- - A name and a constraint (<b>requests@^2.23.0</b>)
186
- - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)
187
- - A git url with a revision\
188
- (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)
189
- - A file path (<b>../my-package/my-package.whl</b>)
190
- - A directory (<b>../my-package/</b>)
191
- - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)
192
- """
200
+ You can specify a package in the following forms:
201
+ - A single name (<b>requests</b>): this will search for matches on PyPI
202
+ - A name and a constraint (<b>requests@^2.23.0</b>)
203
+ - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)
204
+ - A git url with a revision\
205
+ (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)
206
+ - A file path (<b>../my-package/my-package.whl</b>)
207
+ - A directory (<b>../my-package/</b>)
208
+ - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)
209
+ """
193
210
194
211
help_displayed = False
195
- if self .confirm (question_text , True ):
196
- if self .io .is_interactive ():
197
- self .line (help_message )
198
- help_displayed = True
212
+ if is_interactive and self .confirm (question_text , True ):
213
+ self .line (help_message )
214
+ help_displayed = True
199
215
requirements .update (
200
216
self ._format_requirements (self ._determine_requirements ([]))
201
217
)
202
- if self .io .is_interactive ():
203
- self .line ("" )
218
+ self .line ("" )
204
219
205
220
dev_requirements : Requirements = {}
206
221
if self .option ("dev-dependency" ):
@@ -211,44 +226,61 @@ def handle(self) -> int:
211
226
question_text = (
212
227
"Would you like to define your development dependencies interactively?"
213
228
)
214
- if self .confirm (question_text , True ):
215
- if self . io . is_interactive () and not help_displayed :
229
+ if is_interactive and self .confirm (question_text , True ):
230
+ if not help_displayed :
216
231
self .line (help_message )
217
232
218
233
dev_requirements .update (
219
234
self ._format_requirements (self ._determine_requirements ([]))
220
235
)
221
- if self .io .is_interactive ():
222
- self .line ("" )
223
236
224
- layout_ = layout ("standard" )(
237
+ self .line ("" )
238
+
239
+ layout_ = layout (layout_name )(
225
240
name ,
226
241
version ,
227
242
description = description ,
228
243
author = authors [0 ] if authors else None ,
229
- license = license ,
244
+ readme_format = readme_format ,
245
+ license = license_name ,
230
246
python = python ,
231
247
dependencies = requirements ,
232
248
dev_dependencies = dev_requirements ,
233
249
)
234
250
251
+ create_layout = not project_path .exists ()
252
+
253
+ if create_layout :
254
+ layout_ .create (project_path , with_pyproject = False )
255
+
235
256
content = layout_ .generate_poetry_content ()
236
257
for section , item in content .items ():
237
258
pyproject .data .append (section , item )
238
259
239
- if self . io . is_interactive () :
260
+ if is_interactive :
240
261
self .line ("<info>Generated file</info>" )
241
262
self .line ("" )
242
263
self .line (pyproject .data .as_string ().replace ("\r \n " , "\n " ))
243
264
self .line ("" )
244
265
245
- if not self .confirm ("Do you confirm generation?" , True ):
266
+ if is_interactive and not self .confirm ("Do you confirm generation?" , True ):
246
267
self .line_error ("<error>Command aborted</error>" )
247
268
248
269
return 1
249
270
250
271
pyproject .save ()
251
272
273
+ if create_layout :
274
+ path = project_path .resolve ()
275
+
276
+ with suppress (ValueError ):
277
+ path = path .relative_to (Path .cwd ())
278
+
279
+ self .line (
280
+ f"Created package <info>{ layout_ ._package_name } </> in"
281
+ f" <fg=blue>{ path .as_posix ()} </>"
282
+ )
283
+
252
284
return 0
253
285
254
286
def _generate_choice_list (
@@ -276,7 +308,11 @@ def _determine_requirements(
276
308
requires : list [str ],
277
309
allow_prereleases : bool = False ,
278
310
source : str | None = None ,
311
+ is_interactive : bool | None = None ,
279
312
) -> list [dict [str , Any ]]:
313
+ if is_interactive is None :
314
+ is_interactive = self .io .is_interactive ()
315
+
280
316
if not requires :
281
317
result = []
282
318
@@ -366,7 +402,7 @@ def _determine_requirements(
366
402
if package :
367
403
result .append (constraint )
368
404
369
- if self . io . is_interactive () :
405
+ if is_interactive :
370
406
package = self .ask (follow_up_question )
371
407
372
408
return result
0 commit comments