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
a8f6b5b5
Commit
a8f6b5b5
authored
May 26, 2022
by
Randy Döring
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
provider/solver: support for duplicate direct origin dependencies with same version
parent
8cb3aab3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
81 additions
and
37 deletions
+81
-37
src/poetry/puzzle/provider.py
+16
-24
tests/puzzle/test_provider.py
+7
-12
tests/puzzle/test_solver.py
+58
-1
No files found.
src/poetry/puzzle/provider.py
View file @
a8f6b5b5
...
...
@@ -612,39 +612,31 @@ class Provider:
# An example of this is:
# - pypiwin32 (220); sys_platform == "win32" and python_version >= "3.6"
# - pypiwin32 (219); sys_platform == "win32" and python_version < "3.6"
#
# Additional care has to be taken to ensure that hidden constraints like that
# of source type, reference etc. are taking into consideration when duplicates
# are identified.
duplicates
:
dict
[
tuple
[
str
,
str
|
None
,
str
|
None
,
str
|
None
,
str
|
None
],
list
[
Dependency
]
]
=
{}
duplicates
:
dict
[
str
,
list
[
Dependency
]]
=
defaultdict
(
list
)
for
dep
in
dependencies
:
key
=
(
dep
.
complete_name
,
dep
.
source_type
,
dep
.
source_url
,
dep
.
source_reference
,
dep
.
source_subdirectory
,
)
if
key
not
in
duplicates
:
duplicates
[
key
]
=
[]
duplicates
[
key
]
.
append
(
dep
)
duplicates
[
dep
.
complete_name
]
.
append
(
dep
)
dependencies
=
[]
for
key
,
deps
in
duplicates
.
items
():
for
dep_name
,
deps
in
duplicates
.
items
():
if
len
(
deps
)
==
1
:
dependencies
.
append
(
deps
[
0
])
continue
extra_keys
=
", "
.
join
(
k
for
k
in
key
[
1
:]
if
k
is
not
None
)
dep_name
=
f
"{key[0]} ({extra_keys})"
if
extra_keys
else
key
[
0
]
self
.
debug
(
f
"<debug>Duplicate dependencies for {dep_name}</debug>"
)
deps
=
self
.
_merge_dependencies_by_marker
(
deps
)
deps
=
self
.
_merge_dependencies_by_constraint
(
deps
)
non_direct_origin_deps
:
list
[
Dependency
]
=
[]
direct_origin_deps
:
list
[
Dependency
]
=
[]
for
dep
in
deps
:
if
dep
.
is_direct_origin
():
direct_origin_deps
.
append
(
dep
)
else
:
non_direct_origin_deps
.
append
(
dep
)
deps
=
(
self
.
_merge_dependencies_by_constraint
(
self
.
_merge_dependencies_by_marker
(
non_direct_origin_deps
)
)
+
direct_origin_deps
)
if
len
(
deps
)
==
1
:
self
.
debug
(
f
"<debug>Merging requirements for {deps[0]!s}</debug>"
)
dependencies
.
append
(
deps
[
0
])
...
...
tests/puzzle/test_provider.py
View file @
a8f6b5b5
...
...
@@ -514,27 +514,25 @@ def test_search_for_file_wheel_with_extras(provider: Provider):
}
def
test_complete_package_preserves_source_type
(
provider
:
Provider
)
->
None
:
def
test_complete_package_preserves_source_type
(
provider
:
Provider
,
root
:
ProjectPackage
)
->
None
:
fixtures
=
Path
(
__file__
)
.
parent
.
parent
/
"fixtures"
project_dir
=
fixtures
.
joinpath
(
"with_conditional_path_deps"
)
poetry
=
Factory
()
.
create_poetry
(
cwd
=
project_dir
)
for
folder
in
[
"demo_one"
,
"demo_two"
]:
path
=
(
project_dir
/
folder
)
.
as_posix
()
root
.
add_dependency
(
Factory
.
create_dependency
(
"demo"
,
{
"path"
:
path
}))
complete_package
=
provider
.
complete_package
(
DependencyPackage
(
poetry
.
package
.
to_dependency
(),
poetry
.
package
)
DependencyPackage
(
root
.
to_dependency
(),
root
)
)
requires
=
complete_package
.
package
.
all_requires
assert
len
(
requires
)
==
2
assert
{
requires
[
0
]
.
source_url
,
requires
[
1
]
.
source_url
}
==
{
project_dir
.
joinpath
(
"demo_one"
)
.
as_posix
(),
project_dir
.
joinpath
(
"demo_two"
)
.
as_posix
(),
}
assert
{
str
(
requires
[
0
]
.
marker
),
str
(
requires
[
1
]
.
marker
)}
==
{
'sys_platform == "linux"'
,
'sys_platform == "win32"'
,
}
def
test_complete_package_preserves_source_type_with_subdirectories
(
...
...
@@ -545,7 +543,6 @@ def test_complete_package_preserves_source_type_with_subdirectories(
{
"git"
:
"https://github.com/demo/subdirectories.git"
,
"subdirectory"
:
"one"
,
"platform"
:
"linux"
,
},
)
dependency_one_copy
=
Factory
.
create_dependency
(
...
...
@@ -553,7 +550,6 @@ def test_complete_package_preserves_source_type_with_subdirectories(
{
"git"
:
"https://github.com/demo/subdirectories.git"
,
"subdirectory"
:
"one-copy"
,
"platform"
:
"win32"
,
},
)
dependency_two
=
Factory
.
create_dependency
(
...
...
@@ -567,7 +563,6 @@ def test_complete_package_preserves_source_type_with_subdirectories(
{
"git"
:
"https://github.com/demo/subdirectories.git"
,
"subdirectory"
:
"one"
,
"platform"
:
"linux"
,
},
)
)
...
...
tests/puzzle/test_solver.py
View file @
a8f6b5b5
...
...
@@ -1418,7 +1418,7 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved(
assert
len
(
complete_package
.
all_requires
)
==
2
git
,
pypi
=
complete_package
.
all_requires
pypi
,
git
=
complete_package
.
all_requires
assert
isinstance
(
pypi
,
Dependency
)
assert
pypi
==
dependency_pypi
...
...
@@ -1632,6 +1632,63 @@ def test_solver_duplicate_dependencies_sub_dependencies(
)
def
test_duplicate_path_dependencies
(
solver
:
Solver
,
package
:
ProjectPackage
)
->
None
:
solver
.
provider
.
set_package_python_versions
(
"^3.7"
)
fixtures
=
Path
(
__file__
)
.
parent
.
parent
/
"fixtures"
project_dir
=
fixtures
/
"with_conditional_path_deps"
path1
=
(
project_dir
/
"demo_one"
)
.
as_posix
()
demo1
=
Package
(
"demo"
,
"1.2.3"
,
source_type
=
"directory"
,
source_url
=
path1
)
package
.
add_dependency
(
Factory
.
create_dependency
(
"demo"
,
{
"path"
:
path1
,
"markers"
:
"sys_platform == 'linux'"
}
)
)
path2
=
(
project_dir
/
"demo_two"
)
.
as_posix
()
demo2
=
Package
(
"demo"
,
"1.2.3"
,
source_type
=
"directory"
,
source_url
=
path2
)
package
.
add_dependency
(
Factory
.
create_dependency
(
"demo"
,
{
"path"
:
path2
,
"markers"
:
"sys_platform == 'win32'"
}
)
)
transaction
=
solver
.
solve
()
check_solver_result
(
transaction
,
[
{
"job"
:
"install"
,
"package"
:
demo1
},
{
"job"
:
"install"
,
"package"
:
demo2
},
],
)
def
test_duplicate_path_dependencies_same_path
(
solver
:
Solver
,
package
:
ProjectPackage
)
->
None
:
solver
.
provider
.
set_package_python_versions
(
"^3.7"
)
fixtures
=
Path
(
__file__
)
.
parent
.
parent
/
"fixtures"
project_dir
=
fixtures
/
"with_conditional_path_deps"
path1
=
(
project_dir
/
"demo_one"
)
.
as_posix
()
demo1
=
Package
(
"demo"
,
"1.2.3"
,
source_type
=
"directory"
,
source_url
=
path1
)
package
.
add_dependency
(
Factory
.
create_dependency
(
"demo"
,
{
"path"
:
path1
,
"markers"
:
"sys_platform == 'linux'"
}
)
)
package
.
add_dependency
(
Factory
.
create_dependency
(
"demo"
,
{
"path"
:
path1
,
"markers"
:
"sys_platform == 'win32'"
}
)
)
transaction
=
solver
.
solve
()
check_solver_result
(
transaction
,
[{
"job"
:
"install"
,
"package"
:
demo1
}])
def
test_solver_fails_if_dependency_name_does_not_match_package
(
solver
:
Solver
,
repo
:
Repository
,
package
:
ProjectPackage
):
...
...
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