-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathversionstring.py
More file actions
118 lines (108 loc) · 2.89 KB
/
versionstring.py
File metadata and controls
118 lines (108 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
##
# .versionstring
##
"""
PostgreSQL version string parsing.
>>> postgresql.versionstring.split('8.0.1')
(8, 0, 1, None, None)
"""
def split(vstr: str) -> tuple:
"""
Split a PostgreSQL version string into a tuple.
(major, minor, patch, ..., state_class, state_level)
"""
v = vstr.strip().split('.')
# Get rid of the numbers around the state_class (beta,a,dev,alpha, etc)
state_class = v[-1].strip('0123456789')
if state_class:
last_version, state_level = v[-1].split(state_class)
if not state_level:
state_level = None
else:
state_level = int(state_level)
vlist = [int(x or '0') for x in v[:-1]]
if last_version:
vlist.append(int(last_version))
vlist += [None] * (3 - len(vlist))
vlist += [state_class, state_level]
else:
state_level = None
state_class = None
vlist = [int(x or '0') for x in v]
# pad the difference with `None` objects, and +2 for the state_*.
vlist += [None] * ((3 - len(vlist)) + 2)
return tuple(vlist)
def unsplit(vtup: tuple) -> str:
"""
Join a version tuple back into the original version string.
"""
svtup = [str(x) for x in vtup[:-2] if x is not None]
state_class, state_level = vtup[-2:]
return '.'.join(svtup) + ('' if state_class is None else state_class + str(state_level))
def normalize(split_version: tuple) -> tuple:
"""
Given a tuple produced by `split`, normalize the `None` objects into int(0)
or 'final' if it's the ``state_class``.
"""
(*head, state_class, state_level) = split_version
mmp = [x if x is not None else 0 for x in head]
return tuple(mmp + [state_class or 'final', state_level or 0])
default_state_class_priority = [
'dev',
'a',
'alpha',
'b',
'beta',
'rc',
'final',
None,
]
python = repr
def xml(self):
return '<version type="one">\n' + \
' <major>' + str(self[0]) + '</major>\n' + \
' <minor>' + str(self[1]) + '</minor>\n' + \
' <patch>' + str(self[2]) + '</patch>\n' + \
' <state>' + str(self[-2]) + '</state>\n' + \
' <level>' + str(self[-1]) + '</level>\n' + \
'</version>'
def sh(self):
return """PG_VERSION_MAJOR=%s
PG_VERSION_MINOR=%s
PG_VERSION_PATCH=%s
PG_VERSION_STATE=%s
PG_VERSION_LEVEL=%s""" %(
str(self[0]),
str(self[1]),
str(self[2]),
str(self[-2]),
str(self[-1]),
)
if __name__ == '__main__':
import sys
import os
from optparse import OptionParser
op = OptionParser()
op.add_option('-f', '--format',
type='choice',
dest='format',
help='format of output information',
choices=('sh', 'xml', 'python'),
default='sh',
)
op.add_option('-n', '--normalize',
action='store_true',
dest='normalize',
help='replace missing values with defaults',
default=False,
)
op.set_usage(op.get_usage().strip() + ' "version to parse"')
co, ca = op.parse_args()
if len(ca) != 1:
op.error('requires exactly one argument, the version')
else:
v = split(ca[0])
if co.normalize:
v = normalize(v)
sys.stdout.write(getattr(sys.modules[__name__], co.format)(v))
sys.stdout.write(os.linesep)