15150
1616"""
1717
18- def split (vstr ):
18+ def split (vstr : str ) -> (
19+ 'major' ,'minor' ,'patch' ,...,'state_class' ,'state_level'
20+ ):
1921 """
2022 Split a PostgreSQL version string into a tuple
21- (major,minor,patch,state_class,state_level)
23+ (major,minor,patch,..., state_class,state_level)
2224 """
23- v = vstr .strip ().split ('.' , 3 )
25+ v = vstr .strip ().split ('.' )
2426
25- # Get rid of the numbers around the state_class (beta,a,dev,alpha)
27+ # Get rid of the numbers around the state_class (beta,a,dev,alpha, etc )
2628 state_class = v [- 1 ].strip ('0123456789' )
2729 if state_class :
28- last_version_num , state_level = v [- 1 ].split (state_class )
30+ last_version , state_level = v [- 1 ].split (state_class )
2931 if not state_level :
3032 state_level = None
3133 else :
3234 state_level = int (state_level )
35+ vlist = [int (x or '0' ) for x in v [:- 1 ]]
36+ if last_version :
37+ vlist .append (int (last_version ))
38+ vlist += [None ] * (3 - len (vlist ))
39+ vlist += [state_class , state_level ]
3340 else :
34- last_version_num = v [- 1 ]
3541 state_level = None
3642 state_class = None
43+ vlist = [int (x or '0' ) for x in v ]
44+ # pad the difference with `None` objects, and +2 for the state_*.
45+ vlist += [None ] * ((3 - len (vlist )) + 2 )
46+ return tuple (vlist )
3747
38- if last_version_num :
39- last_version_num = int (last_version_num )
40- else :
41- last_version_num = None
42-
43- if len (v ) == 3 :
44- major = int (v [0 ])
45- if v [1 ]:
46- minor = int (v [1 ])
47- else :
48- minor = None
49- patch = last_version_num
50- elif len (v ) == 2 :
51- major = int (v [0 ])
52- minor = last_version_num
53- patch = None
54- else :
55- major = last_version_num
56- minor = None
57- patch = None
58-
59- return (
60- major ,
61- minor ,
62- patch ,
63- state_class ,
64- state_level
48+ def unsplit (vtup : tuple ) -> str :
49+ 'join a version tuple back into the original version string'
50+ svtup = [str (x ) for x in vtup [:- 2 ] if x is not None ]
51+ state_class , state_level = vtup [- 2 :]
52+ return '.' .join (svtup ) + (
53+ '' if state_class is None else state_class + str (state_level )
6554 )
6655
67- def unsplit (vtup ):
68- 'join a version tuple back into a version string'
69- return '%s%s%s%s%s' % (
70- vtup [0 ],
71- vtup [1 ] is not None and '.' + str (vtup [1 ]) or '' ,
72- vtup [2 ] is not None and '.' + str (vtup [2 ]) or '' ,
73- vtup [3 ] is not None and str (vtup [3 ]) or '' ,
74- vtup [4 ] is not None and str (vtup [4 ]) or ''
56+ def normalize (split_version : "a tuple returned by `split`" ) -> tuple :
57+ """
58+ Given a tuple produced by `split`, normalize the `None` objects into int(0)
59+ or 'final' if it's the ``state_class``
60+ """
61+ (* head , state_class , state_level ) = split_version
62+ mmp = [x if x is not None else 0 for x in head ]
63+ return tuple (
64+ mmp + [state_class or 'final' , state_level or 0 ]
7565 )
7666
7767default_state_class_priority = [
@@ -81,6 +71,7 @@ def unsplit(vtup):
8171 'b' ,
8272 'beta' ,
8373 'rc' ,
74+ 'final' ,
8475 None ,
8576]
8677
@@ -108,17 +99,15 @@ def compare(
10899 raise ValueError ("second argument has unknown state class %r" % (v2 [- 2 ],))
109100 return cmp (v1l , v2l )
110101
111-
112- def python (self ):
113- return repr (self )
102+ python = repr
114103
115104def xml (self ):
116105 return '<version type="one">\n ' + \
117106 ' <major>' + str (self [0 ]) + '</major>\n ' + \
118107 ' <minor>' + str (self [1 ]) + '</minor>\n ' + \
119108 ' <patch>' + str (self [2 ]) + '</patch>\n ' + \
120- ' <state>' + str (self [3 ]) + '</state>\n ' + \
121- ' <level>' + str (self [4 ]) + '</level>\n ' + \
109+ ' <state>' + str (self [- 2 ]) + '</state>\n ' + \
110+ ' <level>' + str (self [- 1 ]) + '</level>\n ' + \
122111 '</version>'
123112
124113def sh (self ):
@@ -130,12 +119,13 @@ def sh(self):
130119 str (self [0 ]),
131120 str (self [1 ]),
132121 str (self [2 ]),
133- str (self [3 ]),
134- str (self [4 ]),
122+ str (self [- 2 ]),
123+ str (self [- 1 ]),
135124 )
136125
137126if __name__ == '__main__' :
138127 import sys
128+ import os
139129 from optparse import OptionParser
140130 op = OptionParser ()
141131 op .add_option ('-f' , '--format' ,
@@ -145,20 +135,19 @@ def sh(self):
145135 choices = ('sh' , 'xml' , 'python' ),
146136 default = 'sh' ,
147137 )
148- op .add_option ('-t' , '--type' ,
149- type = 'choice' ,
150- dest = 'type' ,
151- help = 'type of version string to parse' ,
152- choices = ('auto' , 'one' ,),
153- default = 'auto' ,
138+ op .add_option ('-n' , '--normalize' ,
139+ action = 'store_true' ,
140+ dest = 'normalize' ,
141+ help = 'replace missing values with defaults' ,
142+ default = False ,
154143 )
155144 op .set_usage (op .get_usage ().strip () + ' "version to parse"' )
156145 co , ca = op .parse_args ()
157146 if len (ca ) != 1 :
158147 op .error ('requires exactly one argument, the version' )
159- if co .type != 'auto' :
160- v = getattr (sys .modules [__name__ ], co .type ).parse (ca [0 ])
161148 else :
162149 v = split (ca [0 ])
163- sys .stdout .write (getattr (v , co .format )())
164- sys .stdout .write ('\n ' )
150+ if co .normalize :
151+ v = normalize (v )
152+ sys .stdout .write (getattr (sys .modules [__name__ ], co .format )(v ))
153+ sys .stdout .write (os .linesep )
0 commit comments