-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRomanRotate.py
executable file
·147 lines (134 loc) · 4.96 KB
/
RomanRotate.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
import sys
import os
import re
import getopt
import ctypes
import shutil
libc = ctypes.CDLL('libc.so.6')
def debug(argv):
global verbose
if verbose:
print >>sys.stderr, "DBG: %s" % argv
def dec2rom(input):
"""
Convert a decimal to Roman numerals.
"""
assert(isinstance(input, int)), "expected integer, got %s" % type(input)
assert(-1 < input < 4000), "Argument must be between 0 and 3999"
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
result = ""
for i in range(len(ints)):
count = int(input / ints[i])
result += nums[i] * count
input -= ints[i] * count
return result
def rom2dec(input):
"""
Convert a roman numeral to a decimal.
"""
assert(isinstance(input, basestring)), "expected string, got %s" % type(input)
assert(re.match(r'^[MDCLXVI]*$', input)), "not a valid roman numeral: %s" % input
input = input.upper()
nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I']
ints = [1000, 500, 100, 50, 10, 5, 1]
retValue = 0
for i in range(len(input)):
value = ints[nums.index(input[i])]
# If the next place holds a larger number, this value is negative.
try:
if ints[nums.index(input[i +1])] > value:
value *= -1
except IndexError:
# there is no next place.
pass
retValue += value
# Easiest test for validity...
if dec2rom(retValue) == input:
return retValue
else:
raise ValueError, 'input is not a valid roman numeral: %s' % input
def keys(value):
if re.match(r'([MDCLXVI]*)', value):
debug("Roman: %s, Decimal %s" % (value, rom2dec(value)))
return((rom2dec(value), value))
else:
return((value, dec2rom(value)))
def usage():
print """
Usage: %s [-v] [-h] [-d delimiter] [-l] [-t] file [file]
Description: Performs logrotation with roman numbering.
-v Verbose, show debug output
-h Help, show this usage
-d delimiter delimiter between filename and roman extension
deault; '.'
-l List the rotates files ordered by number
-t Reverse rotation or list
Attention: this might cause loss of data in the most recent logfile!
file the filename without numbers, i.e. "logfile.log" or "/path/to/logfile.log"
""" % sys.argv[0]
class FileList(set):
def __init__(self, directory, filename, delimiter):
if(directory!=''):
self._directory = directory
else:
self._directory = '.'
self._filename = filename
self._delimiter = delimiter
debug('Getting files for %s in directory %s' % (self._filename, self._directory))
for file in os.listdir(self._directory):
try:
parts = re.split(r'(%s)([%s]*)([MCXDVIL]*)' % (self._filename, self._delimiter), file)
if parts[1] == self._filename:
debug('Adding: %s %s' % (file, parts))
self.add(keys(parts[3]) + (parts[1], file,))
except Exception, err:
debug(err)
debug('Ignoring: %s' % file)
pass
def sort(self, reverse=False):
return sorted(self, key=lambda file: file[0], reverse=reverse)
if __name__ == "__main__":
global verbose
verbose = False
listOnly = False
reverse = False
delimiter = '.'
optlist, args = getopt.getopt(sys.argv[1:], 'lthvd:')
for option, value in optlist:
if(option == '-v'):
verbose = True
if(option == '-l'):
listOnly = True
if(option == '-t'):
reverse = True
if(option == '-d'):
delimiter = optarg
if(option == '-h'):
usage()
exit
debug('Verbose is on')
debug('Filenames: %s' % args)
for item in args:
debug('Processing: %s' % item)
myList = FileList(os.path.dirname(item), os.path.basename(item), delimiter)
if listOnly:
for file in myList.sort(reverse):
print file[3]
else:
for file in myList.sort(not reverse):
number = dec2rom(file[0] - (+1 if reverse else -1))
filename = file[2] + (("." + number) if number != "" else "")
if file[3] == item and filename == '%s.I' % item:
# make sure all cached writes are flushed to disk, sync twice
libc.sync()
libc.sync()
# Copy the logfile and truncate it. This way it keeps
# it's original inode.
shutil.copy2(file[3], filename)
open(file[3], 'w').close()
libc.sync()
else:
debug('renaming %s to %s.' % (file[3], "%s" % filename))
os.rename(file[3], "%s" % filename)