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
ea7d9d1f
Unverified
Commit
ea7d9d1f
authored
Jun 19, 2020
by
Sébastien Eustace
Committed by
GitHub
Jun 19, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add solutions for common errors (#2396)
parent
b3980622
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
196 additions
and
7 deletions
+196
-7
poetry.lock
+4
-4
poetry/console/config/application_config.py
+10
-0
poetry/mixology/failure.py
+8
-1
poetry/mixology/solutions/__init__.py
+0
-0
poetry/mixology/solutions/providers/__init__.py
+1
-0
poetry/mixology/solutions/providers/python_requirement_solution_provider.py
+30
-0
poetry/mixology/solutions/solutions/__init__.py
+1
-0
poetry/mixology/solutions/solutions/python_requirement_solution.py
+52
-0
poetry/mixology/version_solver.py
+5
-1
pyproject.toml
+1
-0
tests/mixology/solutions/__init__.py
+0
-0
tests/mixology/solutions/providers/__init__.py
+0
-0
tests/mixology/solutions/providers/test_python_requirement_solution_provider.py
+42
-0
tests/mixology/solutions/solutions/__init__.py
+0
-0
tests/mixology/solutions/solutions/test_python_requirement_solution.py
+41
-0
tests/mixology/version_solver/test_python_constraint.py
+1
-1
No files found.
poetry.lock
View file @
ea7d9d1f
...
@@ -215,7 +215,7 @@ version = "0.4.3"
...
@@ -215,7 +215,7 @@ version = "0.4.3"
[[package]]
[[package]]
category = "main"
category = "main"
description = "Updated configparser from Python 3.7 for Python 2.6+."
description = "Updated configparser from Python 3.7 for Python 2.6+."
marker = "python_version
>= \"2.7\" and python_version < \"2.8\" or python_version == \"2.7\" and python_version == \"2.7\" or python_version < \"3
\""
marker = "python_version
< \"3\" or python_version >= \"2.7\" and python_version < \"2.8
\""
name = "configparser"
name = "configparser"
optional = false
optional = false
python-versions = ">=2.6"
python-versions = ">=2.6"
...
@@ -228,7 +228,7 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytes
...
@@ -228,7 +228,7 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2)", "pytes
[[package]]
[[package]]
category = "main"
category = "main"
description = "Backports and enhancements for the contextlib module"
description = "Backports and enhancements for the contextlib module"
marker = "python_version
>= \"2.7\" and python_version < \"2.8\" or python_version < \"3.4
\""
marker = "python_version
< \"3.4\" or python_version >= \"2.7\" and python_version < \"2.8
\""
name = "contextlib2"
name = "contextlib2"
optional = false
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
...
@@ -446,7 +446,7 @@ testing = ["packaging", "importlib-resources"]
...
@@ -446,7 +446,7 @@ testing = ["packaging", "importlib-resources"]
[[package]]
[[package]]
category = "main"
category = "main"
description = "Read resources from Python packages"
description = "Read resources from Python packages"
marker = "python_version
>= \"2.7\" and python_version < \"2.8\" or python_version < \"3.7
\""
marker = "python_version
< \"3.7\" or python_version >= \"2.7\" and python_version < \"2.8
\""
name = "importlib-resources"
name = "importlib-resources"
optional = false
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
...
@@ -1512,7 +1512,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
...
@@ -1512,7 +1512,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
[metadata]
content-hash = "
6e86bcf4be1389d9d1dbd87bd5383089bec887c5a7e9c5e48b09b936699e035d
"
content-hash = "
90cb5177483057d7bf7dea367cb6ccf0968861777c801f3bb41b0f745cccdc24
"
python-versions = "~2.7 || ^3.5"
python-versions = "~2.7 || ^3.5"
[metadata.files]
[metadata.files]
...
...
poetry/console/config/application_config.py
View file @
ea7d9d1f
...
@@ -29,6 +29,7 @@ from poetry.console.commands.command import Command
...
@@ -29,6 +29,7 @@ from poetry.console.commands.command import Command
from
poetry.console.commands.env_command
import
EnvCommand
from
poetry.console.commands.env_command
import
EnvCommand
from
poetry.console.logging.io_formatter
import
IOFormatter
from
poetry.console.logging.io_formatter
import
IOFormatter
from
poetry.console.logging.io_handler
import
IOHandler
from
poetry.console.logging.io_handler
import
IOHandler
from
poetry.utils._compat
import
PY36
class
ApplicationConfig
(
BaseApplicationConfig
):
class
ApplicationConfig
(
BaseApplicationConfig
):
...
@@ -46,6 +47,15 @@ class ApplicationConfig(BaseApplicationConfig):
...
@@ -46,6 +47,15 @@ class ApplicationConfig(BaseApplicationConfig):
self
.
add_event_listener
(
PRE_HANDLE
,
self
.
register_command_loggers
)
self
.
add_event_listener
(
PRE_HANDLE
,
self
.
register_command_loggers
)
self
.
add_event_listener
(
PRE_HANDLE
,
self
.
set_env
)
self
.
add_event_listener
(
PRE_HANDLE
,
self
.
set_env
)
if
PY36
:
from
poetry.mixology.solutions.providers
import
(
PythonRequirementSolutionProvider
,
)
self
.
_solution_provider_repository
.
register_solution_providers
(
[
PythonRequirementSolutionProvider
]
)
def
register_command_loggers
(
def
register_command_loggers
(
self
,
event
,
event_name
,
_
self
,
event
,
event_name
,
_
):
# type: (PreHandleEvent, str, Any) -> None
):
# type: (PreHandleEvent, str, Any) -> None
...
...
poetry/mixology/failure.py
View file @
ea7d9d1f
...
@@ -2,6 +2,8 @@ from typing import Dict
...
@@ -2,6 +2,8 @@ from typing import Dict
from
typing
import
List
from
typing
import
List
from
typing
import
Tuple
from
typing
import
Tuple
from
poetry.core.semver
import
parse_constraint
from
.incompatibility
import
Incompatibility
from
.incompatibility
import
Incompatibility
from
.incompatibility_cause
import
ConflictCause
from
.incompatibility_cause
import
ConflictCause
from
.incompatibility_cause
import
PythonCause
from
.incompatibility_cause
import
PythonCause
...
@@ -44,10 +46,15 @@ class _Writer:
...
@@ -44,10 +46,15 @@ class _Writer:
)
)
required_python_version_notification
=
True
required_python_version_notification
=
True
root_constraint
=
parse_constraint
(
incompatibility
.
cause
.
root_python_version
)
constraint
=
parse_constraint
(
incompatibility
.
cause
.
python_version
)
buffer
.
append
(
buffer
.
append
(
" - {} requires Python {}"
.
format
(
" - {} requires Python {}
, so it will not be satisfied for Python {}
"
.
format
(
incompatibility
.
terms
[
0
]
.
dependency
.
name
,
incompatibility
.
terms
[
0
]
.
dependency
.
name
,
incompatibility
.
cause
.
python_version
,
incompatibility
.
cause
.
python_version
,
root_constraint
.
difference
(
constraint
),
)
)
)
)
...
...
poetry/mixology/solutions/__init__.py
0 → 100644
View file @
ea7d9d1f
poetry/mixology/solutions/providers/__init__.py
0 → 100644
View file @
ea7d9d1f
from
.python_requirement_solution_provider
import
PythonRequirementSolutionProvider
poetry/mixology/solutions/providers/python_requirement_solution_provider.py
0 → 100644
View file @
ea7d9d1f
import
re
from
typing
import
List
from
crashtest.contracts.has_solutions_for_exception
import
HasSolutionsForException
from
crashtest.contracts.solution
import
Solution
class
PythonRequirementSolutionProvider
(
HasSolutionsForException
):
def
can_solve
(
self
,
exception
):
# type: (Exception) -> bool
from
poetry.puzzle.exceptions
import
SolverProblemError
if
not
isinstance
(
exception
,
SolverProblemError
):
return
False
m
=
re
.
match
(
"^The current project's Python requirement (.+) is not compatible "
"with some of the required packages Python requirement"
,
str
(
exception
),
)
if
not
m
:
return
False
return
True
def
get_solutions
(
self
,
exception
):
# type: (Exception) -> List[Solution]
from
..solutions.python_requirement_solution
import
PythonRequirementSolution
return
[
PythonRequirementSolution
(
exception
)]
poetry/mixology/solutions/solutions/__init__.py
0 → 100644
View file @
ea7d9d1f
from
.python_requirement_solution
import
PythonRequirementSolution
poetry/mixology/solutions/solutions/python_requirement_solution.py
0 → 100644
View file @
ea7d9d1f
from
crashtest.contracts.solution
import
Solution
class
PythonRequirementSolution
(
Solution
):
def
__init__
(
self
,
exception
):
from
poetry.mixology.incompatibility_cause
import
PythonCause
from
poetry.core.semver
import
parse_constraint
self
.
_title
=
"Check your dependencies Python requirement."
failure
=
exception
.
error
version_solutions
=
[]
for
incompatibility
in
failure
.
_incompatibility
.
external_incompatibilities
:
if
isinstance
(
incompatibility
.
cause
,
PythonCause
):
root_constraint
=
parse_constraint
(
incompatibility
.
cause
.
root_python_version
)
constraint
=
parse_constraint
(
incompatibility
.
cause
.
python_version
)
version_solutions
.
append
(
"For <fg=default;options=bold>{}</>, a possible solution would be "
'to set the `<fg=default;options=bold>python</>` property to <fg=yellow>"{}"</>'
.
format
(
incompatibility
.
terms
[
0
]
.
dependency
.
name
,
root_constraint
.
intersect
(
constraint
),
)
)
description
=
(
"The Python requirement can be specified via the `<fg=default;options=bold>python</>` "
"or `<fg=default;options=bold>markers</>` properties"
)
if
version_solutions
:
description
+=
"
\n\n
"
+
"
\n
"
.
join
(
version_solutions
)
description
+=
"
\n
"
self
.
_description
=
description
@property
def
solution_title
(
self
)
->
str
:
return
self
.
_title
@property
def
solution_description
(
self
):
return
self
.
_description
@property
def
documentation_links
(
self
):
return
[
"https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies"
,
"https://python-poetry.org/docs/dependency-specification/#using-environment-markers"
,
]
poetry/mixology/version_solver.py
View file @
ea7d9d1f
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import
time
import
time
from
typing
import
TYPE_CHECKING
from
typing
import
Any
from
typing
import
Any
from
typing
import
Dict
from
typing
import
Dict
from
typing
import
List
from
typing
import
List
...
@@ -11,7 +12,6 @@ from poetry.core.packages import Package
...
@@ -11,7 +12,6 @@ from poetry.core.packages import Package
from
poetry.core.packages
import
ProjectPackage
from
poetry.core.packages
import
ProjectPackage
from
poetry.core.semver
import
Version
from
poetry.core.semver
import
Version
from
poetry.core.semver
import
VersionRange
from
poetry.core.semver
import
VersionRange
from
poetry.puzzle.provider
import
Provider
from
.failure
import
SolveFailure
from
.failure
import
SolveFailure
from
.incompatibility
import
Incompatibility
from
.incompatibility
import
Incompatibility
...
@@ -25,6 +25,10 @@ from .set_relation import SetRelation
...
@@ -25,6 +25,10 @@ from .set_relation import SetRelation
from
.term
import
Term
from
.term
import
Term
if
TYPE_CHECKING
:
from
poetry.puzzle.provider
import
Provider
_conflict
=
object
()
_conflict
=
object
()
...
...
pyproject.toml
View file @
ea7d9d1f
...
@@ -27,6 +27,7 @@ python = "~2.7 || ^3.5"
...
@@ -27,6 +27,7 @@ python = "~2.7 || ^3.5"
poetry-core
=
"^1.0.0a6"
poetry-core
=
"^1.0.0a6"
cleo
=
"^0.8.1"
cleo
=
"^0.8.1"
clikit
=
"^0.6.2"
clikit
=
"^0.6.2"
crashtest
=
{
version
=
"^0.3.0"
,
python
=
"^3.6"
}
requests
=
"^2.18"
requests
=
"^2.18"
cachy
=
"^0.3.0"
cachy
=
"^0.3.0"
requests-toolbelt
=
"^0.8.0"
requests-toolbelt
=
"^0.8.0"
...
...
tests/mixology/solutions/__init__.py
0 → 100644
View file @
ea7d9d1f
tests/mixology/solutions/providers/__init__.py
0 → 100644
View file @
ea7d9d1f
tests/mixology/solutions/providers/test_python_requirement_solution_provider.py
0 → 100644
View file @
ea7d9d1f
import
pytest
from
poetry.core.packages.dependency
import
Dependency
from
poetry.mixology.failure
import
SolveFailure
from
poetry.mixology.incompatibility
import
Incompatibility
from
poetry.mixology.incompatibility_cause
import
NoVersionsCause
from
poetry.mixology.incompatibility_cause
import
PythonCause
from
poetry.mixology.term
import
Term
from
poetry.puzzle.exceptions
import
SolverProblemError
from
poetry.utils._compat
import
PY36
@pytest.mark.skipif
(
not
PY36
,
reason
=
"Error solutions are only available for Python ^3.6"
)
def
test_it_can_solve_python_incompatibility_solver_errors
():
from
poetry.mixology.solutions.providers
import
PythonRequirementSolutionProvider
from
poetry.mixology.solutions.solutions
import
PythonRequirementSolution
incompatibility
=
Incompatibility
(
[
Term
(
Dependency
(
"foo"
,
"^1.0"
),
True
)],
PythonCause
(
"^3.5"
,
">=3.6"
)
)
exception
=
SolverProblemError
(
SolveFailure
(
incompatibility
))
provider
=
PythonRequirementSolutionProvider
()
assert
provider
.
can_solve
(
exception
)
assert
isinstance
(
provider
.
get_solutions
(
exception
)[
0
],
PythonRequirementSolution
)
@pytest.mark.skipif
(
not
PY36
,
reason
=
"Error solutions are only available for Python ^3.6"
)
def
test_it_cannot_solve_other_solver_errors
():
from
poetry.mixology.solutions.providers
import
PythonRequirementSolutionProvider
incompatibility
=
Incompatibility
(
[
Term
(
Dependency
(
"foo"
,
"^1.0"
),
True
)],
NoVersionsCause
()
)
exception
=
SolverProblemError
(
SolveFailure
(
incompatibility
))
provider
=
PythonRequirementSolutionProvider
()
assert
not
provider
.
can_solve
(
exception
)
tests/mixology/solutions/solutions/__init__.py
0 → 100644
View file @
ea7d9d1f
tests/mixology/solutions/solutions/test_python_requirement_solution.py
0 → 100644
View file @
ea7d9d1f
import
pytest
from
clikit.io.buffered_io
import
BufferedIO
from
poetry.core.packages.dependency
import
Dependency
from
poetry.mixology.failure
import
SolveFailure
from
poetry.mixology.incompatibility
import
Incompatibility
from
poetry.mixology.incompatibility_cause
import
PythonCause
from
poetry.mixology.term
import
Term
from
poetry.puzzle.exceptions
import
SolverProblemError
from
poetry.utils._compat
import
PY36
@pytest.mark.skipif
(
not
PY36
,
reason
=
"Error solutions are only available for Python ^3.6"
)
def
test_it_provides_the_correct_solution
():
from
poetry.mixology.solutions.solutions
import
PythonRequirementSolution
incompatibility
=
Incompatibility
(
[
Term
(
Dependency
(
"foo"
,
"^1.0"
),
True
)],
PythonCause
(
"^3.5"
,
">=3.6"
)
)
exception
=
SolverProblemError
(
SolveFailure
(
incompatibility
))
solution
=
PythonRequirementSolution
(
exception
)
title
=
"Check your dependencies Python requirement."
description
=
"""
\
The Python requirement can be specified via the `python` or `markers` properties
For foo, a possible solution would be to set the `python` property to ">=3.6,<4.0"
\
"""
links
=
[
"https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies"
,
"https://python-poetry.org/docs/dependency-specification/#using-environment-markers"
,
]
assert
title
==
solution
.
solution_title
assert
(
description
==
BufferedIO
()
.
remove_format
(
solution
.
solution_description
)
.
strip
()
)
assert
links
==
solution
.
documentation_links
tests/mixology/version_solver/test_python_constraint.py
View file @
ea7d9d1f
...
@@ -10,7 +10,7 @@ def test_dependency_does_not_match_root_python_constraint(root, provider, repo):
...
@@ -10,7 +10,7 @@ def test_dependency_does_not_match_root_python_constraint(root, provider, repo):
error
=
"""The current project's Python requirement (^3.6)
\
error
=
"""The current project's Python requirement (^3.6)
\
is not compatible with some of the required packages Python requirement:
is not compatible with some of the required packages Python requirement:
- foo requires Python <3.5
- foo requires Python <3.5
, so it will not be satisfied for Python >=3.6,<4.0
Because no versions of foo match !=1.0.0
Because no versions of foo match !=1.0.0
and foo (1.0.0) requires Python <3.5, foo is forbidden.
and foo (1.0.0) requires Python <3.5, foo is forbidden.
...
...
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