<div><span style="color: rgb(160, 160, 168); ">On Tuesday, February 26, 2013 at 7:08 AM, Michael Foord wrote:</span></div>
                <blockquote type="cite" style="border-left-style:solid;border-width:1px;margin-left:0px;padding-left:10px;">
                    <span><div><div><br><br><div>On 26 February 2013 03:22, Nick Coghlan <span dir="ltr"><<a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>></span> wrote:<br><blockquote type="cite"><div>
<div>On Tue, Feb 26, 2013 at 11:06 AM, Donald Stufft <<a href="mailto:donald.stufft@gmail.com">donald.stufft@gmail.com</a>> wrote:<br>
> !=1.3 allowing 1.3.1 makes sense to me. 1.3 is equivalent to 1.3.0, 1.3.1 !=<br>
> 1.3.0.<br>
<br>
</div>Nope, the PEP explicitly disclaims the historical equivalence between<br>
1.3 and 1.3.0. It has to, because they're very different when it comes<br>
to what the PEP now calls a "compatible release clause"<br>
(<a href="http://www.python.org/dev/peps/pep-0426/#compatible-release" target="_blank">http://www.python.org/dev/peps/pep-0426/#compatible-release</a>), Ruby<br>
gems call a "pessimistic version constraint"<br>
(<a href="http://docs.rubygems.org/read/chapter/16#page74" target="_blank">http://docs.rubygems.org/read/chapter/16#page74</a>), PHP composer calls<br>
"next significant release"<br>
(<a href="http://getcomposer.org/doc/01-basic-usage.md#package-versions" target="_blank">http://getcomposer.org/doc/01-basic-usage.md#package-versions</a>) and<br>
Node.js npm calls "Tilde version range"<br>
(<a href="https://npmjs.org/doc/json.html" target="_blank">https://npmjs.org/doc/json.html</a>) (Note: I also checked CPAN version<br>
ordering to see if it had an equivalent operation, but Perl's approach<br>
appears to be closer to the way pkg_resources handles ordering:<br>
<a href="http://search.cpan.org/~jpeacock/version-0.9901/lib/version.pod#How_to_compare_version_objects" target="_blank">http://search.cpan.org/~jpeacock/version-0.9901/lib/version.pod#How_to_compare_version_objects</a>)<br>

<br>
However, while numeric maintenance releases are part of the problem<br>
here, the real issue is correctly handling *post* releases.<br>
<br>
Does "== 1.3" allow "1.3.post1"? Does "!= 1.3" allow "1.3.post1"? Both? Neither?<br>
<br>
If you use strict string matching for == and !=, then "!= 1.3" will<br>
allow "1.3.post1", which is utterly insane given the PEP's recommended<br>
usage of post releases solely for non-functional changes like tweaking<br>
the release notes or project metadata.<br>
<br>
Leaving == as strict and making != prefix based breaks the fundamental<br>
relationship between equality and inequality checks, so that's also<br>
not a reasonable option.<br>
<br>
That leaves making both == and != prefix based as the most reasonable<br>
alternative, as "!= 1.3" will then correctly reject "1.3.post1" and<br>
the appropriate logical relationship is maintained between the two<br>
operators.<br>
<br>
However, you then need a way to spell an *exact* version request (for<br>
use with tools like zc.buildout and pip freeze that are designed to<br>
snapshot an application configuration rather than for dependency<br>
publication in an index).<br>
<br></div></blockquote><div><br></div><div>The current tools are strict with regards to equality - and in dependency pinning I would see it as *surprising* that specifying "==1.3" installs some version that isn't precisely 1.3. Having "==" mean approximately-equal, instead of the-same-as, seems like a mistake to me.</div>
<div><br></div><div>Michael</div></div></div></div></span></blockquote><div>I agree with this, == should mean EXACTLY 1.3, != should mean EXACTLY NOT 1.3.</div><div><br></div><div>However because these aren't strings and are versions we can understand that:</div><div><br></div><div>1.3 == 1.3.0 == 1.3.0.0 == 1.3.0.0.0 etc etc. </div><blockquote type="cite" style="border-left-style:solid;border-width:1px;margin-left:0px;padding-left:10px;"><span><div><div><div><div><br></div><div> </div><blockquote type="cite"><div>
My plan for that use case is to allow "is" as a comparison operator<br>
that means exactly what it says: the version required is precisely the<br>
specified version, with no prefix matching or release compatibility<br>
assessments allowed.<br>
<br>
That gives a natural progression in dependency constraints from more<br>
permissive to less permissive:<br>
<br>
    Compatible version: some-dist (X.Y)  # roughly equivalent to (>=<br>
X.Y, < X+1.dev0)<br>
    Version equality: some-dist (== X.Y)  # roughly equivalent to (>=<br>
X.Y, < X.Y+1.dev0)<br>
    Version identity: some-dist (is X.Y)  # must be exactly X.Y<br>
<br>
All three clauses also have clearly defined use cases:<br>
<br>
1. Use compatible version clauses in published metadata for stable<br>
dependencies with a good backwards compatibility policy<br>
2. Use version equality clauses in published metadata for dependencies<br>
without a good backwards compatibility policy<br>
3. Use version identity clauses for application and deployment<br>
dependency snapshots<br>
<div><div><br>
Cheers,<br>
Nick.<br>
<br>
--<br>
Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>   |   Brisbane, Australia<br>
_______________________________________________<br>
Distutils-SIG maillist  -  <a href="mailto:Distutils-SIG@python.org">Distutils-SIG@python.org</a><br>
<a href="http://mail.python.org/mailman/listinfo/distutils-sig" target="_blank">http://mail.python.org/mailman/listinfo/distutils-sig</a><br>
</div></div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><pre cols="72"><a href="http://www.voidspace.org.uk/" target="_blank">http://www.voidspace.org.uk/</a><br><br>May you do good and not evil<br>May you find forgiveness for yourself and forgive others<br>
May you share freely, never taking more than you give.<br>-- the sqlite blessing <a href="http://www.sqlite.org/different.html" target="_blank">http://www.sqlite.org/different.html</a></pre>

</div></div></span>
                 
                 
                 
                 
                </blockquote>
                 
                <div>
                    <br>
                </div>