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