Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate develop option and rename to editable #106

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 140 additions & 43 deletions poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from typing import Any
from typing import Dict
from typing import Generator
from typing import List
from typing import Optional
from typing import Union
Expand All @@ -27,6 +28,11 @@ class Factory(object):
Factory class to create various elements needed by Poetry.
"""

DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP = {
"allows-prereleases": "allow-prereleases",
"develop": "editable",
}

def create_poetry(
self, cwd=None, with_dev=True
): # type: (Optional[Path]. bool) -> Poetry
Expand Down Expand Up @@ -182,49 +188,40 @@ def create_dependency(
constraint = "*"

if isinstance(constraint, dict):
optional = constraint.get("optional", False)
python_versions = constraint.get("python")
platform = constraint.get("platform")
markers = constraint.get("markers")
if "allows-prereleases" in constraint:
message = (
'The "{}" dependency specifies '
'the "allows-prereleases" property, which is deprecated. '
'Use "allow-prereleases" instead.'.format(name)
)
warn(message, DeprecationWarning)
logger.warning(message)

allows_prereleases = constraint.get(
"allow-prereleases", constraint.get("allows-prereleases", False)
constraint_without_deprecated_keys = cls.as_constraint_with_deprecated_keys_renamed_to_current_keys(
dependency_name=name, constraint=constraint,
)
optional = constraint_without_deprecated_keys.get("optional", False)
python_versions = constraint_without_deprecated_keys.get("python")
platform = constraint_without_deprecated_keys.get("platform")
markers = constraint_without_deprecated_keys.get("markers")

if "git" in constraint:
if "git" in constraint_without_deprecated_keys:
# VCS dependency
dependency = VCSDependency(
name,
"git",
constraint["git"],
branch=constraint.get("branch", None),
tag=constraint.get("tag", None),
rev=constraint.get("rev", None),
constraint_without_deprecated_keys["git"],
branch=constraint_without_deprecated_keys.get("branch", None),
tag=constraint_without_deprecated_keys.get("tag", None),
rev=constraint_without_deprecated_keys.get("rev", None),
category=category,
optional=optional,
develop=constraint.get("develop", False),
extras=constraint.get("extras", []),
editable=constraint_without_deprecated_keys.get("editable", False),
extras=constraint_without_deprecated_keys.get("extras", []),
)
elif "file" in constraint:
file_path = Path(constraint["file"])
elif "file" in constraint_without_deprecated_keys:
file_path = Path(constraint_without_deprecated_keys["file"])

dependency = FileDependency(
name,
file_path,
category=category,
base=root_dir,
extras=constraint.get("extras", []),
extras=constraint_without_deprecated_keys.get("extras", []),
)
elif "path" in constraint:
path = Path(constraint["path"])
elif "path" in constraint_without_deprecated_keys:
path = Path(constraint_without_deprecated_keys["path"])

if root_dir:
is_file = root_dir.joinpath(path).is_file()
Expand All @@ -238,7 +235,7 @@ def create_dependency(
category=category,
optional=optional,
base=root_dir,
extras=constraint.get("extras", []),
extras=constraint_without_deprecated_keys.get("extras", []),
)
else:
dependency = DirectoryDependency(
Expand All @@ -247,27 +244,31 @@ def create_dependency(
category=category,
optional=optional,
base=root_dir,
develop=constraint.get("develop", False),
extras=constraint.get("extras", []),
editable=constraint_without_deprecated_keys.get(
"editable", False
),
extras=constraint_without_deprecated_keys.get("extras", []),
)
elif "url" in constraint:
elif "url" in constraint_without_deprecated_keys:
dependency = URLDependency(
name,
constraint["url"],
constraint_without_deprecated_keys["url"],
category=category,
optional=optional,
extras=constraint.get("extras", []),
extras=constraint_without_deprecated_keys.get("extras", []),
)
else:
version = constraint["version"]
version = constraint_without_deprecated_keys["version"]

dependency = Dependency(
name,
version,
optional=optional,
category=category,
allows_prereleases=allows_prereleases,
extras=constraint.get("extras", []),
allows_prereleases=constraint_without_deprecated_keys.get(
"allow_prereleases", False
),
extras=constraint_without_deprecated_keys.get("extras", []),
)

if not markers:
Expand Down Expand Up @@ -296,7 +297,7 @@ def create_dependency(
if not marker.is_any():
dependency.marker = marker

dependency.source_name = constraint.get("source")
dependency.source_name = constraint_without_deprecated_keys.get("source")
else:
dependency = Dependency(name, constraint, category=category)

Expand Down Expand Up @@ -329,12 +330,23 @@ def validate(
if not isinstance(constraint, dict):
continue

if "allows-prereleases" in constraint:
result["warnings"].append(
'The "{}" dependency specifies '
'the "allows-prereleases" property, which is deprecated. '
'Use "allow-prereleases" instead.'.format(name)
)
for deprecated_key in cls.deprecated_keys():
if deprecated_key in constraint:
if cls.constraint_has_deprecated_key_current_key_conflict(
constraint, deprecated_key
):
result["errors"].append(
cls.deprecated_constraint_key_current_key_conflict_error_message(
dependency_name=name,
deprecated_key=deprecated_key,
)
)
else:
result["warnings"].append(
cls.constraint_key_deprecation_message(
dependency_name=name, key=deprecated_key
)
)

# Checking for scripts with extras
if "scripts" in config:
Expand Down Expand Up @@ -371,3 +383,88 @@ def locate(cls, cwd): # type: (Path) -> Path
cwd
)
)

@classmethod
def deprecated_keys(cls): # type: () -> Generator[str, None, None]
for key in cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP:
yield key

@classmethod
def as_constraint_with_deprecated_keys_renamed_to_current_keys(
cls, dependency_name, constraint
): # type: (str, Dict[str, Any]) -> Dict[str, Any]
constraint_with_renamed_keys = {}
for key, value in constraint.items():
if cls.is_deprecated_constraint_key(key):
cls.raise_on_deprecated_constraint_key_current_key_conflict(
dependency_name, constraint, key
)
cls.warn_constraint_key_is_deprecated(dependency_name, key)
current_key = cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP[key]
constraint_with_renamed_keys[current_key] = value
else:
constraint_with_renamed_keys[key] = value
return constraint_with_renamed_keys

@classmethod
def raise_on_deprecated_constraint_key_current_key_conflict(
cls, dependency_name, constraint, deprecated_key
): # type: (str, Dict[str, Any], str) -> None
"""Raise `RuntimeError` when both a deprecated key and it's current, updated counterpart (key) are contained in constraint."""
if cls.constraint_has_deprecated_key_current_key_conflict(
constraint, deprecated_key
):
raise RuntimeError(
cls.deprecated_constraint_key_current_key_conflict_error_message(
dependency_name, deprecated_key,
)
)

@classmethod
def constraint_has_deprecated_key_current_key_conflict(
cls, constraint, deprecated_key
): # type: (Dict[str, Any], str) -> bool
current_key = cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP[deprecated_key]
return current_key in constraint

@classmethod
def deprecated_constraint_key_current_key_conflict_error_message(
cls, dependency_name, deprecated_key
): # type: (str, str) -> str
current_key = cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP[deprecated_key]
return (
'The "{dependency_name}" dependency specifies '
'both the "{current_key}" property and the deprecated "{deprecated_key}" property. '
'Please remove "{deprecated_key}" and resolve value conflicts!'.format(
dependency_name=dependency_name,
current_key=current_key,
deprecated_key=deprecated_key,
)
)

@classmethod
def is_deprecated_constraint_key(cls, key): # type: (str) -> bool
return key in cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP

@classmethod
def warn_constraint_key_is_deprecated(
cls, dependency_name, key
): # type: (str, str) -> None
message = cls.constraint_key_deprecation_message(dependency_name, key)
warn(message, DeprecationWarning)
logging.warning(message)

@classmethod
def constraint_key_deprecation_message(
cls, dependency_name, key
): # type: (str, str) -> str
current_key = cls.DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP[key]
return (
'The "{dependency_name}" dependency specifies '
'the "{deprecated_key}" property, which is deprecated. '
'Use "{current_key}" instead.'.format(
dependency_name=dependency_name,
deprecated_key=key,
current_key=current_key,
)
)
14 changes: 12 additions & 2 deletions poetry/core/json/schemas/poetry-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,14 @@
"type": "string"
}
},
"editable": {
"type": "boolean",
"description": "Whether to install the dependency in editable mode."
},
"develop": {
"type": "boolean",
"description": "Whether to install the dependency in development mode."
"description": "Whether to install the dependency in editable mode.",
"deprecated": true
}
}
},
Expand Down Expand Up @@ -435,9 +440,14 @@
"type": "string"
}
},
"editable": {
"type": "boolean",
"description": "Whether to install the dependency in editable mode."
},
"develop": {
"type": "boolean",
"description": "Whether to install the dependency in development mode."
"description": "Whether to install the dependency in editable mode.",
"deprecated": true
}
}
},
Expand Down
30 changes: 26 additions & 4 deletions poetry/core/packages/directory_dependency.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List
from typing import Set
from typing import Union
from warnings import warn

from poetry.core.pyproject import PyProjectTOML
from poetry.core.utils._compat import Path
Expand All @@ -16,6 +17,7 @@ def __init__(
category="main", # type: str
optional=False, # type: bool
base=None, # type: Path
editable=False, # type: bool
develop=False, # type: bool
extras=None, # type: Union[List[str], Set[str]]
):
Expand All @@ -29,7 +31,18 @@ def __init__(
except FileNotFoundError:
raise ValueError("Directory {} does not exist".format(self._path))

self._develop = develop
# TODO: Remove the following once poetry has been updated to use editable in source.
if develop:
if editable:
raise ValueError(
'Deprecated "develop" parameter may not be passed with new "editable" parameter. '
'Only use "editable"!'
)
warn(
'"develop" parameter is deprecated, use "editable" instead.',
DeprecationWarning,
)
self._editable = editable or develop
self._supports_poetry = False

if not self._full_path.exists():
Expand Down Expand Up @@ -75,8 +88,17 @@ def base(self):
return self._base

@property
def develop(self):
return self._develop
def editable(self):
return self._editable

# TODO: Remove the following once poetry has been updated to use editable in source.
@property
def develop(self): # type: () -> bool
warn(
'"develop" property is deprecated, use "editable" instead.',
DeprecationWarning,
)
return self.editable

def supports_poetry(self):
return self._supports_poetry
Expand All @@ -91,7 +113,7 @@ def with_constraint(self, constraint):
base=self.base,
optional=self.is_optional(),
category=self.category,
develop=self._develop,
editable=self._editable,
extras=self._extras,
)

Expand Down
Loading