Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
python-poetry
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
python-poetry
Commits
58e3cc23
Unverified
Commit
58e3cc23
authored
May 23, 2018
by
Sébastien Eustace
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix dependency overriding in dev-dependencies
parent
47a083ca
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
214 additions
and
47 deletions
+214
-47
CHANGELOG.md
+1
-0
poetry/puzzle/provider.py
+1
-0
poetry/puzzle/solver.py
+121
-47
tests/puzzle/test_solver.py
+91
-0
No files found.
CHANGELOG.md
View file @
58e3cc23
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
### Fixed
### Fixed
-
Fixed the dependency resolver selecting incompatible packages.
-
Fixed the dependency resolver selecting incompatible packages.
-
Fixed override of dependency with dependency with extras in
`dev-dependencies`
.
## [0.9.1] - 2018-05-18
## [0.9.1] - 2018-05-18
...
...
poetry/puzzle/provider.py
View file @
58e3cc23
...
@@ -330,6 +330,7 @@ class Provider:
...
@@ -330,6 +330,7 @@ class Provider:
package
.
python_versions
=
complete_package
.
python_versions
package
.
python_versions
=
complete_package
.
python_versions
package
.
platform
=
complete_package
.
platform
package
.
platform
=
complete_package
.
platform
package
.
hashes
=
complete_package
.
hashes
package
.
hashes
=
complete_package
.
hashes
package
.
extras
=
complete_package
.
extras
return
[
return
[
r
for
r
in
package
.
requires
r
for
r
in
package
.
requires
...
...
poetry/puzzle/solver.py
View file @
58e3cc23
...
@@ -107,14 +107,22 @@ class Solver:
...
@@ -107,14 +107,22 @@ class Solver:
)
)
)
)
def
_get_tags_for_package
(
self
,
package
,
packages
,
requested
,
original
=
None
):
def
_get_graph_for_package
(
self
,
package
,
packages
,
requested
,
original
=
None
):
category
=
'dev'
graph
=
{
optional
=
True
package
.
name
:
{
'category'
:
'dev'
,
root
=
None
'optional'
:
True
,
'python_version'
:
None
,
'platform'
:
None
,
'dependencies'
:
{},
'parents'
:
{},
},
}
roots
=
[]
for
dep
in
requested
:
for
dep
in
requested
:
if
dep
.
name
==
package
.
name
:
if
dep
.
name
==
package
.
name
:
root
=
dep
root
s
.
append
(
dep
)
origins
=
[]
origins
=
[]
for
pkg
in
packages
:
for
pkg
in
packages
:
...
@@ -126,63 +134,129 @@ class Solver:
...
@@ -126,63 +134,129 @@ class Solver:
if
dep
.
name
==
package
.
name
:
if
dep
.
name
==
package
.
name
:
origins
.
append
((
pkg
,
dep
))
origins
.
append
((
pkg
,
dep
))
if
root
is
not
None
and
not
origins
:
if
roots
and
(
not
origins
or
len
(
roots
)
>
1
):
# Original dependency
# Root dependency
if
len
(
roots
)
==
1
:
root
=
roots
[
0
]
else
:
root1
=
[
r
for
r
in
roots
if
r
.
category
==
'main'
][
0
]
root2
=
[
r
for
r
in
roots
if
r
.
category
==
'dev'
][
0
]
if
root1
.
extras
==
root2
.
extras
or
original
is
None
:
root
=
root1
else
:
root1_extra_dependencies
=
[]
for
extra
in
root1
.
extras
:
if
extra
in
package
.
extras
:
for
dep
in
package
.
extras
[
extra
]:
root1_extra_dependencies
.
append
(
dep
.
name
)
root2_extra_dependencies
=
[]
for
extra
in
root2
.
extras
:
if
extra
in
package
.
extras
:
for
dep
in
package
.
extras
[
extra
]:
root2_extra_dependencies
.
append
(
dep
.
name
)
if
(
original
.
name
in
root1_extra_dependencies
and
original
.
name
in
root2_extra_dependencies
):
root
=
root1
elif
original
.
name
in
root2_extra_dependencies
:
root
=
root2
else
:
root
=
root1
category
=
root
.
category
category
=
root
.
category
optional
=
root
.
is_optional
()
optional
=
root
.
is_optional
()
python_version
=
str
(
root
.
python_constraint
)
python_version
=
str
(
root
.
python_constraint
)
platform
=
str
(
root
.
platform_constraint
)
platform
=
str
(
root
.
platform_constraint
)
return
category
,
optional
,
python_version
,
platform
graph
[
package
.
name
][
'category'
]
=
category
graph
[
package
.
name
][
'optional'
]
=
optional
graph
[
package
.
name
][
'python_version'
]
=
python_version
graph
[
package
.
name
][
'platform'
]
=
platform
python_versions
=
[]
return
graph
platforms
=
[]
for
pkg
,
dep
in
origins
:
for
pkg
,
dep
in
origins
:
python_version
=
dep
.
python_versions
graph
[
package
.
name
][
'dependencies'
][
pkg
.
name
]
=
{
platform
=
dep
.
platform
'constraint'
:
dep
.
pretty_constraint
,
'python_version'
:
dep
.
python_versions
,
(
top_category
,
'platform'
:
dep
.
platform
,
top_optional
,
}
top_python_version
,
graph
[
package
.
name
][
'parents'
]
.
update
(
top_platform
)
=
self
.
_get_tags_for_package
(
self
.
_get_graph_for_package
(
pkg
,
packages
,
requested
,
original
=
package
pkg
,
packages
,
requested
,
original
=
package
)
)
)
if
top_category
==
'main'
:
return
graph
category
=
top_category
optional
=
optional
and
top_optional
def
_get_tags_for_package
(
self
,
package
,
packages
,
requested
):
graph
=
self
.
_get_graph_for_package
(
package
,
packages
,
requested
)[
package
.
name
]
# Take the most restrictive constraints
return
self
.
_get_tags_from_graph
(
graph
,
packages
)
if
top_python_version
is
not
None
:
if
python_version
is
not
None
:
previous
=
parse_constraint
(
python_version
)
current
=
parse_constraint
(
top_python_version
)
if
previous
.
allows_all
(
current
):
def
_get_tags_from_graph
(
self
,
graph
,
packages
):
python_versions
.
append
(
top_python_version
)
category
=
graph
[
'category'
]
else
:
optional
=
graph
[
'optional'
]
python_versions
.
append
(
python_version
)
python_version
=
graph
[
'python_version'
]
else
:
platform
=
graph
[
'platform'
]
python_versions
.
append
(
top_python_version
)
elif
python_version
is
not
None
:
python_versions
.
append
(
python_version
)
if
top_platform
is
not
None
:
if
not
graph
[
'parents'
]:
if
platform
is
not
None
:
# Root dependency
previous
=
GenericConstraint
.
parse
(
platform
)
return
category
,
optional
,
python_version
,
platform
current
=
GenericConstraint
.
parse
(
top_platform
)
if
top_platform
!=
'*'
and
previous
.
matches
(
current
):
python_versions
=
[]
platforms
.
append
(
top_platform
)
platforms
=
[]
else
:
platforms
.
append
(
platform
)
for
parent_name
,
parent_graph
in
graph
[
'parents'
]
.
items
():
else
:
dep_python_version
=
graph
[
'dependencies'
][
parent_name
][
'python_version'
]
platforms
.
append
(
top_platform
)
dep_platform
=
graph
[
'dependencies'
][
parent_name
][
'platform'
]
elif
platform
is
not
None
:
platforms
.
append
(
platform
)
for
pkg
in
packages
:
if
pkg
.
name
==
parent_name
:
(
top_category
,
top_optional
,
top_python_version
,
top_platform
)
=
self
.
_get_tags_from_graph
(
parent_graph
,
packages
)
if
category
is
None
or
category
!=
'main'
:
category
=
top_category
optional
=
optional
and
top_optional
# Take the most restrictive constraints
if
top_python_version
is
not
None
:
if
dep_python_version
is
not
None
:
previous
=
parse_constraint
(
dep_python_version
)
current
=
parse_constraint
(
top_python_version
)
if
previous
.
allows_all
(
current
):
python_versions
.
append
(
top_python_version
)
else
:
python_versions
.
append
(
dep_python_version
)
else
:
python_versions
.
append
(
top_python_version
)
elif
dep_python_version
is
not
None
:
python_versions
.
append
(
dep_python_version
)
if
top_platform
is
not
None
:
if
dep_platform
is
not
None
:
previous
=
GenericConstraint
.
parse
(
dep_platform
)
current
=
GenericConstraint
.
parse
(
top_platform
)
if
top_platform
!=
'*'
and
previous
.
matches
(
current
):
platforms
.
append
(
top_platform
)
else
:
platforms
.
append
(
dep_platform
)
else
:
platforms
.
append
(
top_platform
)
elif
dep_platform
is
not
None
:
platforms
.
append
(
dep_platform
)
break
if
not
python_versions
:
if
not
python_versions
:
python_version
=
None
python_version
=
None
...
...
tests/puzzle/test_solver.py
View file @
58e3cc23
...
@@ -574,3 +574,94 @@ def test_solver_sub_dependencies_with_not_supported_python_version(solver, repo,
...
@@ -574,3 +574,94 @@ def test_solver_sub_dependencies_with_not_supported_python_version(solver, repo,
check_solver_result
(
ops
,
[
check_solver_result
(
ops
,
[
{
'job'
:
'install'
,
'package'
:
package_a
},
{
'job'
:
'install'
,
'package'
:
package_a
},
])
])
def
test_solver_with_dependency_in_both_main_and_dev_dependencies
(
solver
,
repo
,
package
):
package
.
python_versions
=
'^3.5'
package
.
add_dependency
(
'A'
)
package
.
add_dependency
(
'A'
,
{
'version'
:
'*'
,
'extras'
:
[
'foo'
]},
category
=
'dev'
)
package_a
=
get_package
(
'A'
,
'1.0'
)
package_a
.
extras
[
'foo'
]
=
[
get_dependency
(
'C'
)]
package_a
.
add_dependency
(
'C'
,
{
'version'
:
'^1.0'
,
'optional'
:
True
})
package_a
.
add_dependency
(
'B'
,
{
'version'
:
'^1.0'
})
package_b
=
get_package
(
'B'
,
'1.0'
)
package_c
=
get_package
(
'C'
,
'1.0'
)
package_c
.
add_dependency
(
'D'
,
'^1.0'
)
package_d
=
get_package
(
'D'
,
'1.0'
)
repo
.
add_package
(
package_a
)
repo
.
add_package
(
package_b
)
repo
.
add_package
(
package_c
)
repo
.
add_package
(
package_d
)
ops
=
solver
.
solve
()
check_solver_result
(
ops
,
[
{
'job'
:
'install'
,
'package'
:
package_b
},
{
'job'
:
'install'
,
'package'
:
package_c
},
{
'job'
:
'install'
,
'package'
:
package_d
},
{
'job'
:
'install'
,
'package'
:
package_a
},
])
b
=
ops
[
0
]
.
package
c
=
ops
[
1
]
.
package
d
=
ops
[
2
]
.
package
a
=
ops
[
3
]
.
package
assert
d
.
category
==
'dev'
assert
c
.
category
==
'dev'
assert
b
.
category
==
'main'
assert
a
.
category
==
'main'
def
test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_dependent
(
solver
,
repo
,
package
):
package
.
add_dependency
(
'A'
)
package
.
add_dependency
(
'E'
)
package
.
add_dependency
(
'A'
,
{
'version'
:
'*'
,
'extras'
:
[
'foo'
]},
category
=
'dev'
)
package_a
=
get_package
(
'A'
,
'1.0'
)
package_a
.
extras
[
'foo'
]
=
[
get_dependency
(
'C'
)]
package_a
.
add_dependency
(
'C'
,
{
'version'
:
'^1.0'
,
'optional'
:
True
})
package_a
.
add_dependency
(
'B'
,
{
'version'
:
'^1.0'
})
package_b
=
get_package
(
'B'
,
'1.0'
)
package_c
=
get_package
(
'C'
,
'1.0'
)
package_c
.
add_dependency
(
'D'
,
'^1.0'
)
package_d
=
get_package
(
'D'
,
'1.0'
)
package_e
=
get_package
(
'E'
,
'1.0'
)
package_e
.
add_dependency
(
'A'
,
'^1.0'
)
repo
.
add_package
(
package_a
)
repo
.
add_package
(
package_b
)
repo
.
add_package
(
package_c
)
repo
.
add_package
(
package_d
)
repo
.
add_package
(
package_e
)
ops
=
solver
.
solve
()
check_solver_result
(
ops
,
[
{
'job'
:
'install'
,
'package'
:
package_b
},
{
'job'
:
'install'
,
'package'
:
package_c
},
{
'job'
:
'install'
,
'package'
:
package_d
},
{
'job'
:
'install'
,
'package'
:
package_a
},
{
'job'
:
'install'
,
'package'
:
package_e
},
])
b
=
ops
[
0
]
.
package
c
=
ops
[
1
]
.
package
d
=
ops
[
2
]
.
package
a
=
ops
[
3
]
.
package
e
=
ops
[
4
]
.
package
assert
d
.
category
==
'dev'
assert
c
.
category
==
'dev'
assert
b
.
category
==
'main'
assert
a
.
category
==
'main'
assert
e
.
category
==
'main'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment