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

Fix Compatibility Check for Prereleases #7723

Merged
merged 5 commits into from Jan 7, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 24 additions & 8 deletions jupyterlab/commands.py
Expand Up @@ -1186,7 +1186,7 @@ def _populate_staging(self, name=None, version=None, static_url=None,
json.dump(data, fid, indent=4)

# copy known-good yarn.lock if missing
lock_path = pjoin(staging, 'yarn.lock')
lock_path = pjoin(staging, 'yarn.lock')
lock_template = pjoin(HERE, 'staging', 'yarn.lock')
if self.registry != YARN_DEFAULT_REGISTRY: # Replace on the fly the yarn repository see #3658
with open(lock_template, encoding='utf-8') as f:
Expand Down Expand Up @@ -1726,7 +1726,10 @@ def sort_key(key_value):

for (key, value) in latest_deps.items():
if key in singletons:
c = _compare_ranges(core_deps[key], value)
# Drop prereleases in comparisons to allow extension authors
# to not have to update their versions for each
# Jupyterlab prerelease version.
c = _compare_ranges(core_deps[key], value, drop_prerelease1=True)
lab_newer_than_latest = lab_newer_than_latest or c < 0
latest_newer_than_lab = latest_newer_than_lab or c > 0

Expand Down Expand Up @@ -1774,7 +1777,7 @@ def _node_check(logger):

def _yarn_config(logger):
"""Get the yarn configuration.

Returns
-------
{"yarn config": dict, "npm config": dict} if unsuccessfull the subdictionary are empty
Expand Down Expand Up @@ -1942,26 +1945,30 @@ def _validate_compatibility(extension, deps, core_data):

for (key, value) in deps.items():
if key in singletons:
overlap = _test_overlap(core_deps[key], value)
# Drop prereleases in comparisons to allow extension authors
# to not have to update their versions for each
# Jupyterlab prerelease version.
overlap = _test_overlap(core_deps[key], value, drop_prerelease1=True)
if overlap is False:
errors.append((key, core_deps[key], value))

return errors


def _test_overlap(spec1, spec2):
def _test_overlap(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False):
"""Test whether two version specs overlap.

Returns `None` if we cannot determine compatibility,
otherwise whether there is an overlap
"""
cmp = _compare_ranges(spec1, spec2)
cmp = _compare_ranges(spec1, spec2, drop_prerelease1=drop_prerelease1,
drop_prerelease2=drop_prerelease2)
if cmp is None:
return
return cmp == 0


def _compare_ranges(spec1, spec2):
def _compare_ranges(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False):
"""Test whether two version specs overlap.

Returns `None` if we cannot determine compatibility,
Expand All @@ -1982,6 +1989,12 @@ def _compare_ranges(spec1, spec2):
y1 = r2.set[0][0].semver
y2 = r2.set[0][-1].semver

if x1.prerelease and drop_prerelease1:
x1 = x1.inc('patch')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this behavior an option in the function? As a standalone function, it's surprising that it ignores the prerelease option on just one end of one of the ranges. Would we get the same end result if we had an "increment prerelease" flag as an argument, and then just did this logic on both ends of both ranges?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we can make this behavior optional in the standalone function. It only has an effect on the lower end of the range, since ~2.0.0-b1 gets interpreted originally as 2.0.0-b1 <= x < 2.1.0 and converted to 2.0.0 <= x < 2.1.0. By doing it on the lower end of the first argument, we are saying that we don't do compatibility checks within our own prerelease cycle only.


if y1.prerelease and drop_prerelease2:
y1 = y1.inc('patch')

o1 = r1.set[0][0].operator
o2 = r2.set[0][0].operator

Expand Down Expand Up @@ -2107,7 +2120,10 @@ def _compat_error_age(errors):
any_newer = False

for _, jlab, ext in errors:
c = _compare_ranges(ext, jlab)
# Drop prereleases in comparisons to allow extension authors
# to not have to update their versions for each
# Jupyterlab prerelease version.
c = _compare_ranges(ext, jlab, drop_prerelease1=True)
any_newer = any_newer or c < 0
any_older = any_older or c > 0
if any_older and not any_newer:
Expand Down