-
Notifications
You must be signed in to change notification settings - Fork 96
Feature request: concise "compatibility" matching #284
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
Comments
@sbrudenell Thanks for your report.
Yes, but what you mean by "compatible with"? I have a vague idea, but "In the face of ambiguity, refuse the temptation to guess." 😉 Could you help me to understand what you mean by giving a more verbose example? Thanks! 👍 |
Maybe a clearer way to say what I mean is: x -> y is not a breaking change. Another way: x matches "^y" according to npm version matching idioms. (or probably a subset of the idiom, not treating version 0 as special) Does that make sense? |
For my use case I'd most like to be able to use the PEP 440 version of "compatible": https://www.python.org/dev/peps/pep-0440/#compatible-release I would also greatly appreciate being able to use the operators from that pep in the code, for example
|
Isn't the specification enough? |
The spec is about API compatibility, but doesn't have any info about version compatibility, eg |
Did you mean version matching? OP asked for a method to check if a caller implementing version X is compatible with a callee implementing version Y, using somthing like
That's exactly what SemVer is about.
This is where I'm lost, SemVer describes exactly the rules to answer that. |
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Funny coincidence, I've played around with these extended matching parts in PR #367. 😄 It may or may not be integrated into the main branch, depending on the outcome of your comments. If you want to give it a try, please comment on the respective PR. It goes in the direction to #241. @sbrudenell, @Lexicality and @rafalkrupinski would that help? Any comments are greatly appreciated. |
I'm looking for trivial matching according to semver rules
|
Would something like this be useful? def iscompatible(v1: Version, v2: Version):
if v1.major != v2.major:
return False
if v1.minor < v2.minor:
return False
if v1.prerelease != v2.prerelease:
return False
return True
>>> v1 = Version(1, 2, 3)
>>> v2 = Version(1, 1, 4)
>>> v3 = Version(1, 3, 5)
>>> iscompatible(v1, v2)
True
>>> iscompatible(v1, v3)
False The code is derived from your description. Certainly we could optimize it. |
@tomschr Also, I'd rather have a method instead of a function, so there is a clear
I'd like to put a version in my model classes and yaml files, so the program can verify if it can handle the files, similar to Kubernetes. Cheers |
Handling the semantics of the distinction between caller and callee is going to be a bit of a job. The most obvious but implicit way I can think of is encoding this information in the order of the arguments to the function, like so: def iscompatible(caller: Version, callee: Version):
... In a more explicit way, but still mostly implicit, there is the option of creating a method on def iscompatible(self, callee: Version):
... As I write it down, I realise that having these arg names actually makes them very explicit, so they may not be that bad choices in the end. |
Not a native English speaker, but how about naming it
|
The actual factor that is directional is the dependency relation. The word def compatible_with(self, callee: Version) -> bool: # Quite natural
... There is the convention of prefixing names for boolean values with def is_compatible_with(self, callee: Version) -> bool:
... |
For naming, I've been using variations on def is_breaking(v_from, v_to):
... It implies more direction than "compatible with" |
Both
Thanks! |
An alias would be very confusing, since is 'breaking' is opposite of 'compatible'. ;)
I'm not a user yet, so I don't have a stake here.
Good question. |
The algorithm checks: * if the two majors are different, it's incompatible * if the two majors are equal, but the minor of the callee is lower than the caller, it's incompatible * if both prereleases are present and different, it's incompatible * otherwise it's compatible
From what I understand, the current Just so I understand
Right? |
Possibly yes. 🙂 My brain didn't catch that in the early morning. 😄
Yeah, I'm inclined to make this breaking change in the upcoming semver 3 version.
That's a good point. It seems, that in most cases, people use string types a lot. Maybe let's wait what others have to say here. Maybe they come up with some good arguments pro or against it.
Depends on the function. 😉 For example, the |
It seems to me, the
Correct? In that case, this issue overlaps with PR #367 and it contains exactly that. Maybe in that PR we could rename the private The question could be here, if we want to have these (extended?) comparisons inside the Version class or outsource it to a Spec class. My only concern here is that we should follow some separation of concerns and to not make the Version class too big. |
Not exactly, as @Lexicality rightfully noted, the patch part is ignored. The difference is that SemVer is more about the public API and less about implementation. The API must not change at all between different patch releases so caller v1.2.3 is fully compatible with API of callee v1.2.0 . In my use case (files with version), it's perfectly fine to ignore the patch version. Of course there might be cases when patch should be checked. If so, how about adding a parameter |
I'm not sure thinking of packages is the right approach. SemVer is more about API compatibility. But consider this: I think we're trying to handle two separate use cases:
The extended comparison would handle the former case, |
@Lexicality you are very right indeed. The direction of the relation I was talking about was not that of the dependency, but the bump (I totally misunderstood that). Therefore this would make more sense: def is_compatible_with(self, new: Version) -> bool:
... Or def is_compatible(old: Version, new: Version):
... So please disregard anything I said about dependency relationships, and replace it with old/new relationship instead 😅 |
Thank you for all your input. It gives me a much better picture. However, still we need to solve the following questions:
|
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The algorithm checks: * if the two majors are different, it's incompatible * if the two majors are equal, but the minor of the new version is lower than the old, it's incompatible * if both prereleases are present and different, it's incompatible * otherwise it's compatible The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The algorithm checks: * if the two majors are different, it's incompatible * if the two majors are equal, but the minor of the new version is lower than the old, it's incompatible * if both prereleases are present and different, it's incompatible * otherwise it's compatible The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The algorithm checks: * if the two majors are different, it's incompatible * if the two majors are equal, but the minor of the new version is lower than the old, it's incompatible * if both prereleases are present and different, it's incompatible * otherwise it's compatible The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The result is True, if either of the following is true: * both versions are equal, or * both majors are equal and higher than 0. Same for both minors. Both pre-releases are equal, or * both majors are equal and higher than 0. The minor of b's minor version is higher then a's. Both pre-releases are equal. The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The result is True, if either of the following is true: * both versions are equal, or * both majors are equal and higher than 0. Same for both minors. Both pre-releases are equal, or * both majors are equal and higher than 0. The minor of b's minor version is higher then a's. Both pre-releases are equal. The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The result is True, if either of the following is true: * both versions are equal, or * both majors are equal and higher than 0. Same for both minors. Both pre-releases are equal, or * both majors are equal and higher than 0. The minor of b's minor version is higher then a's. Both pre-releases are equal. The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
* Implement Version.is_compatible() method * Update test cases * Update documentation * Rename isvalid method to is_valid to make it consistent with is_compatible The result is True, if either of the following is true: * both versions are equal, or * both majors are equal and higher than 0. Same for both minors. Both pre-releases are equal, or * both majors are equal and higher than 0. The minor of b's minor version is higher then a's. Both pre-releases are equal. The algorithm does *not* check patches! Co-authored-by: Lexi Robinson <lexi@lexi.org.uk> Co-authored-by: Thomas Laferriere <tlaferriere@users.noreply.github.com> Co-authored-by: Raphael Krupinski <rafalkrupinski@users.noreply.github.com>
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Fix #284: implement "is compatible with" method
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
* Introduce Spec class to deal with such comparisons * Improve documentation * Simplify code in Version.match (delegates to Spec.match)
Use parts of PEP 440
Use parts of PEP 440
I'd really like a concise expression for "is version x compatible with version y?"
Specifically, suppose I write code against one version of an API, and the API exposes a semver-compliant version. Is
v_caller
compatible withv_api
?The most concise expression I can come up with is something like
v_caller <= v_api and v_caller.major == v_api.major
, but I really wish this was simpler and more readable. Maybev_caller.compatible(v_api)
; or maybev_caller.can_call(v_api)
better illustrates which operand is which.I know this would be covered by #241, but its scope is quite broad. I wanted to specifically call out this feature.
The text was updated successfully, but these errors were encountered: