Commits

Floris Bruynooghe  committed 6e46484

Simplify postdev to only allow .postX.devX

This turns the pseudo-format into something like:

N.N[.N]+[abc]N[.N]+[.postN+][.devN+]

So the only valid post and dev combinations are:

1.0.dev2
1.0.post2
1.0.post2.dev2

This greatly simplifies the use of pre- and post-release tags.
Interanlly it means .postX with no .devX gets a final marker appended
so that it sorts after .postX.devX.

  • Participants
  • Parent commits b872df5

Comments (0)

Files changed (3)

     ...  < V('1.0c1')
     ...  < V('1.0.dev456')
     ...  < V('1.0')
-    ...  < V('1.0.dev456post623')
+    ...  < V('1.0.post456.dev623')
     ...  < V('1.0.post456'))
     True
 
 (e.g. Twisted [#twisted]_). For example *after* a "1.2.0" release there might
 be a "1.2.0-r678" release. We used "post" instead of "r" because the "r" is
 ambiguous as to whether it indicates a pre- or post-release.
-Last ".dev456post623" is a development version of a post-release.
+Last ".post456dev623" is a development version of a post-release.
 
 ``verlib`` provides a ``RationalVersion`` class and a
 ``suggest_rational_version`` function.
 
 - the main version part
 - the pre-release part
-- the `devpost` marker part
+- the `postdev` marker part
 
 Examples ::
 

File test_verlib.py

                 (V('1.2.3.4.0b3'), '1.2.3.4b3'),
                 (V('1.2.0.0.0'), '1.2'),
                 (V('1.0.dev345'), '1.0.dev345'),
-                (V('1.0.dev456post623'), '1.0.dev456post623'))
+                (V('1.0.post456.dev623'), '1.0.post456.dev623'))
 
     def test_basic_versions(self):
 
 
     def test_irrational_versions(self):
 
-        irrational = ('1', '1.2a', '1.2.3b', '1.02',
-                      '1.2a03', '1.2a3.04')
+        irrational = ('1', '1.2a', '1.2.3b', '1.02', '1.2a03',
+                      '1.2a3.04', '1.2.dev.2', '1.2dev', '1.2.dev',
+                      '1.2.dev2.post2', '1.2.post2.dev3.post4')
 
         for s in irrational:
             self.assertRaises(IrrationalVersionError, V, s)
         ...  > V('1.0.0a2') > V('1.0.0a1'))
         True
 
-        >>> V('1.0') < V('1.0.dev456post623')
+        >>> V('1.0') < V('1.0.post456.dev623')
         True
 
-        >>> V('1.0.dev456post623') < V('1.0.post456')
+        >>> V('1.0.post456.dev623') < V('1.0.post456')
         True
 
         >>> (V('1.0a1')
         ...  < V('1.0c1')
         ...  < V('1.0.dev456')
         ...  < V('1.0')
-        ...  < V('1.0.dev456post623')  # development version of a post release
+        ...  < V('1.0.post456.dev623')  # development version of a post release
         ...  < V('1.0.post456'))
         True
         """
     pass
 
 # A marker used in the second and third parts of the `parts` tuple, for
-# versions that don't have those segments, to sort properly. A example
+# versions that don't have those segments, to sort properly. An example
 # of versions in sort order ('highest' last):
 #   1.0b1                 ((1,0), ('b',1), ('f',))
 #   1.0.dev345            ((1,0), ('f',),  ('dev', 345))
 #   1.0                   ((1,0), ('f',),  ('f',))
-#   1.0.dev256post345     ((1,0), ('f',),  ('f', 'dev', 256, 'post', 345))
-#   1.0.post345           ((1,0), ('f',),  ('f', 'post', 345))
-#                                   ^        ^
-#   'f' < 'b' ---------------------/         |
-#                                            |
-#   'dev' < 'f' < 'post' -------------------/
-# Other letters would do, bug 'f' for 'final' is kind of nice.
+#   1.0.post256.dev345    ((1,0), ('f',),  ('f', 'post', 256, 'dev', 345))
+#   1.0.post345           ((1,0), ('f',),  ('f', 'post', 345, 'f'))
+#                                   ^        ^                 ^
+#   'f' < 'b' ---------------------/         |                 |
+#                                            |                 |
+#   'dev' < 'f' < 'post' -------------------/                  |
+#                                                              |
+#   'dev' < 'f' ----------------------------------------------/
+# Other letters would do, but 'f' for 'final' is kind of nice.
 FINAL_MARKER = ('f',)
 
 VERSION_RE = re.compile(r'''
         (?P<prerel>[abc])             # 'a'=alpha, 'b'=beta, 'c'=release candidate
         (?P<prerelversion>\d+(?:\.\d+)*)
     )?
-    (?P<devpost>\.((dev(?P<devpost1>\d+)post(?P<devpost2>\d+))|
-                            (dev(?P<dev>\d+))|
-                            (post(?P<post>\d+))))?
+    (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)?
     $''', re.VERBOSE)
 
 class RationalVersion(object):
         else:
             parts.append(FINAL_MARKER)
 
-        if groups.get('devpost') is not None:
+        # postdev
+        if groups.get('postdev'):
+            post = groups.get('post')
             dev = groups.get('dev')
-            post = groups.get('post')
+            postdev = []
+            if post is not None:
+                postdev.extend([FINAL_MARKER[0], 'post', post])
+                if dev is None:  # XXX
+                    postdev.append(FINAL_MARKER[0])
             if dev is not None:
-                parts.append(('dev', dev))
-            elif post is not None:
-                parts.append((FINAL_MARKER[0], 'post', post))
-            else:
-                parts.append((FINAL_MARKER[0],
-                              'dev', groups.get('devpost1'),
-                              'post', groups.get('devpost2')))
+                postdev.extend(['dev', dev])
+            parts.append(tuple(postdev))
         else:
             parts.append(FINAL_MARKER)
         self.parts = tuple(parts)
     def parts_to_str(cls, parts):
         """Transforms a version expressed in tuple into its string
         representation."""
-        main, prerel, devpost = parts
+        # XXX This doesn't check for invalid tuples
+        main, prerel, postdev = parts
         s = '.'.join(str(v) for v in main)
         if prerel is not FINAL_MARKER:
             s += prerel[0]
             s += '.'.join(str(v) for v in prerel[1:])
-        if devpost is not FINAL_MARKER:
-            if devpost[0] == 'f':
-                devpost = devpost[1:]
-            s += '.' + ''.join(str(v) for v in devpost)
+        if postdev and postdev is not FINAL_MARKER:
+            if postdev[0] == 'f':
+                postdev = postdev[1:]
+            i = 0
+            while i < len(postdev):
+                if i % 2 == 0:
+                    s += '.'
+                s += str(postdev[i])
+                i += 1
         return s
 
     def __repr__(self):