Skip to content

Commit 86c4db7

Browse files
committed
Add the ability to add complete dependencies in one go
1 parent abfc3f3 commit 86c4db7

File tree

2 files changed

+144
-6
lines changed

2 files changed

+144
-6
lines changed

poetry/console/commands/init.py

+41-3
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ def _parse_requirements(
336336
cwd = Path.cwd()
337337

338338
for requirement in requirements:
339+
requirement = requirement.strip()
340+
extras = []
341+
extras_m = re.search(r"\[([\w\d,-_]+)\]$", requirement)
342+
if extras_m:
343+
extras = [e.strip() for e in extras_m.group(1).split(",")]
344+
requirement, _ = requirement.split("[")
345+
339346
if requirement.startswith(("git+https://", "git+ssh://")):
340347
url = requirement.lstrip("git+")
341348
rev = None
@@ -348,6 +355,9 @@ def _parse_requirements(
348355
if rev:
349356
pair["rev"] = rev
350357

358+
if extras:
359+
pair["extras"] = extras
360+
351361
package = Provider.get_package_from_vcs(
352362
"git", url, reference=pair.get("rev")
353363
)
@@ -368,19 +378,47 @@ def _parse_requirements(
368378
("name", package.name),
369379
("path", path.relative_to(cwd).as_posix()),
370380
]
381+
+ ([("extras", extras)] if extras else [])
371382
)
372383
)
373384

374385
continue
375386

376-
pair = re.sub("^([^=: ]+)[@=: ](.*)$", "\\1 \\2", requirement.strip())
387+
pair = re.sub(
388+
"^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirement
389+
)
377390
pair = pair.strip()
378391

392+
require = OrderedDict()
379393
if " " in pair:
380394
name, version = pair.split(" ", 2)
381-
result.append({"name": name, "version": version})
395+
require["name"] = name
396+
require["version"] = version
382397
else:
383-
result.append({"name": pair})
398+
m = re.match(
399+
"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.strip()
400+
)
401+
if m:
402+
name, constraint = m.group(1), m.group(2)
403+
extras_m = re.search(r"\[([\w\d,-_]+)\]$", name)
404+
if extras_m:
405+
extras = [e.strip() for e in extras_m.group(1).split(",")]
406+
name, _ = name.split("[")
407+
408+
require["name"] = name
409+
require["version"] = constraint
410+
else:
411+
extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair)
412+
if extras_m:
413+
extras = [e.strip() for e in extras_m.group(1).split(",")]
414+
pair, _ = pair.split("[")
415+
416+
require["name"] = pair
417+
418+
if extras:
419+
require["extras"] = extras
420+
421+
result.append(require)
384422

385423
return result
386424

tests/console/commands/test_add.py

+103-3
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ def test_add_no_constraint(app, repo, installer):
4242
assert content["dependencies"]["cachy"] == "^0.2.0"
4343

4444

45-
def test_add_constraint(app, repo, installer):
45+
def test_add_equal_constraint(app, repo, installer):
4646
command = app.find("add")
4747
tester = CommandTester(command)
4848

4949
repo.add_package(get_package("cachy", "0.1.0"))
5050
repo.add_package(get_package("cachy", "0.2.0"))
5151

52-
tester.execute("cachy=0.1.0")
52+
tester.execute("cachy==0.1.0")
5353

5454
expected = """\
5555
@@ -69,6 +69,67 @@ def test_add_constraint(app, repo, installer):
6969
assert len(installer.installs) == 1
7070

7171

72+
def test_add_greater_constraint(app, repo, installer):
73+
command = app.find("add")
74+
tester = CommandTester(command)
75+
76+
repo.add_package(get_package("cachy", "0.1.0"))
77+
repo.add_package(get_package("cachy", "0.2.0"))
78+
79+
tester.execute("cachy>=0.1.0")
80+
81+
expected = """\
82+
83+
Updating dependencies
84+
Resolving dependencies...
85+
86+
Writing lock file
87+
88+
89+
Package operations: 1 install, 0 updates, 0 removals
90+
91+
- Installing cachy (0.2.0)
92+
"""
93+
94+
assert expected == tester.io.fetch_output()
95+
96+
assert len(installer.installs) == 1
97+
98+
99+
def test_add_constraint_with_extras(app, repo, installer):
100+
command = app.find("add")
101+
tester = CommandTester(command)
102+
103+
cachy1 = get_package("cachy", "0.1.0")
104+
cachy1.extras = {"msgpack": [get_dependency("msgpack-python")]}
105+
msgpack_dep = get_dependency("msgpack-python", ">=0.5 <0.6", optional=True)
106+
cachy1.requires = [msgpack_dep]
107+
108+
repo.add_package(get_package("cachy", "0.2.0"))
109+
repo.add_package(cachy1)
110+
repo.add_package(get_package("msgpack-python", "0.5.3"))
111+
112+
tester.execute("cachy[msgpack]^0.1.0")
113+
114+
expected = """\
115+
116+
Updating dependencies
117+
Resolving dependencies...
118+
119+
Writing lock file
120+
121+
122+
Package operations: 2 installs, 0 updates, 0 removals
123+
124+
- Installing msgpack-python (0.5.3)
125+
- Installing cachy (0.1.0)
126+
"""
127+
128+
assert expected == tester.io.fetch_output()
129+
130+
assert len(installer.installs) == 2
131+
132+
72133
def test_add_constraint_dependencies(app, repo, installer):
73134
command = app.find("add")
74135
tester = CommandTester(command)
@@ -164,6 +225,45 @@ def test_add_git_constraint_with_poetry(app, repo, installer):
164225
assert len(installer.installs) == 2
165226

166227

228+
def test_add_git_constraint_with_extras(app, repo, installer):
229+
command = app.find("add")
230+
tester = CommandTester(command)
231+
232+
repo.add_package(get_package("pendulum", "1.4.4"))
233+
repo.add_package(get_package("cleo", "0.6.5"))
234+
repo.add_package(get_package("tomlkit", "0.5.5"))
235+
236+
tester.execute("git+https://github.com/demo/demo.git[foo,bar]")
237+
238+
expected = """\
239+
240+
Updating dependencies
241+
Resolving dependencies...
242+
243+
Writing lock file
244+
245+
246+
Package operations: 4 installs, 0 updates, 0 removals
247+
248+
- Installing cleo (0.6.5)
249+
- Installing pendulum (1.4.4)
250+
- Installing tomlkit (0.5.5)
251+
- Installing demo (0.1.2 9cf87a2)
252+
"""
253+
254+
assert expected == tester.io.fetch_output()
255+
256+
assert len(installer.installs) == 4
257+
258+
content = app.poetry.file.read()["tool"]["poetry"]
259+
260+
assert "demo" in content["dependencies"]
261+
assert content["dependencies"]["demo"] == {
262+
"git": "https://github.com/demo/demo.git",
263+
"extras": ["foo", "bar"],
264+
}
265+
266+
167267
def test_add_directory_constraint(app, repo, installer, mocker):
168268
p = mocker.patch("poetry.utils._compat.Path.cwd")
169269
p.return_value = Path(__file__) / ".."
@@ -304,7 +404,7 @@ def test_add_file_constraint_sdist(app, repo, installer, mocker):
304404
}
305405

306406

307-
def test_add_constraint_with_extras(app, repo, installer):
407+
def test_add_constraint_with_extras_option(app, repo, installer):
308408
command = app.find("add")
309409
tester = CommandTester(command)
310410

0 commit comments

Comments
 (0)