On Mon, Dec 28, 2009 at 05:37, Terry Reedy <tjreedy@udel.edu> wrote:
If the first x.y release were called x.y.0, (does not sys.version include 0?) then x.y would unambiguously mean the series.
Yeah, well, although sys.version includes the zero, nothing else does. The first releases are called 2.5, which is ambiguous. Both Python and Plone leaves out the zero in the version name. IMO that's a bug. But that's now how it is. However, there are two ways of writing versions that are completely unambiguous and which every programmer will immediately understand: 2.5.0 and 2.5.* Done. The comma is problematic. If you want to specify 2.5 or 2.6, it would be natural to write: Requires-Python: 2.5.*, 2.6.* Which clearly has the comma meaning "or". But it would also make sense to write: Requires-Python: >= 2.5.2, < 3.0.0 Where it is an "and". But trying to leave commas out leaves us with the slightly weird syntax of Requires-Python: >= 2.5.2 and < 3.0.0 or >= 3.1.* And then it's the question of in what order that should be interpreted. And what would Requires-Python: >= 3.1.* or >= 2.5.2 and < 3.0.0 mean? And would Requires-Python: >= 2.5.2 or >= 3.1.* and < 3.0.0 Be legal an mean anything? My conclusion: This is a place where the normal computer logic syntax makes so sense, it's either too restrictive, or too flexible. We need something custom, where we can specify pairs of two versions, min and max and have several pairs. Also, the min version can always be included and the max version excluded. You need to write things like:
= 2.5.2 and < 3.0.0. You never need to write <= 2.5.7, because you can always write < 2.5.8 instead.
Now, this "starting from and then up until but not including" is something that is quite common in Python. Namely when slicing. It works exactly like that. [3:9] means from 3 and up until but not including 9. Hence, a clear and unambiguous and extremely Pythonic way of specifying a version range is: [2.5.2:3.0.0]. No <= or commas anywhere. We can also specify a list of ranges by having semicolons between them. The grammar ends up something like this: versionrequirements ::= 'Requires-Python: ' specificationlist specificationlist ::= specification (; specification)* specification ::= version | "[" [version] ":" [version] "]" version ::= lc_number "." (lc_number | "*") "." [lc_number | "*"] With examples being: Requires-Python: [2.5.2:3.0.0]; [3.1.*:] Or on several rows: Requires-Python: [2.5.2:3.0.0]; [3.1.2:]; [3.2.*] Now, if <=>== etc is deemed necessary, we could use something like this: versionrequirements ::= 'Requires-Python: ' specificationlist specificationlist ::= specification (; specification)* specification ::= version | minimum | maximum | miniumum " " maximum minimum ::= ('>' | '>=') version maximum ::= ('<' | '<=') version version ::= lc_number "." (lc_number | "*") "." [lc_number | "*"] That would mean something like the following: Requires-Python: >= 2.5.2 < 3.0.0; >= 3.1* or more clearer if it's split up in lines: Requires-Python: >= 2.5.2 < 3.0.0; >= 3.1* The following would be illegal: Requires-Python: >= 2.5.2 > 3.0.0 Requires-Python: <= 2.5.2 < 3.0.0 Requires-Python: <= 2.5.2 < 3.0.0 > 3.1* No commas or ands or ors anywhere. But I like the first syntax better.