automated reformat pass

This commit is contained in:
lynxize 2025-06-20 08:58:24 -06:00
parent 66fe9bc514
commit d0d8588e5f
Signed by: lynxize
GPG key ID: 8615849B8532CD77

View file

@ -14,19 +14,22 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from __future__ import print_function
from __future__ import division
from past.builtins import cmp
from __future__ import print_function
from builtins import chr
from builtins import input
from builtins import map
from builtins import range
from past.utils import old_div
from functools import reduce
__title__="KeyJ's iPod shuffle Database Builder"
__version__="1.0"
__author__="Martin Fiedler"
__email__="martin.fiedler@gmx.net"
from past.builtins import cmp
from past.utils import old_div
__title__ = "KeyJ's iPod shuffle Database Builder"
__version__ = "1.0"
__author__ = "Martin Fiedler"
__email__ = "martin.fiedler@gmx.net"
""" VERSION HISTORY
1.0-rc1 (2006-04-26)
@ -71,34 +74,35 @@ __email__="martin.fiedler@gmx.net"
* initial public release, Win32 only
"""
import sys, os, os.path, array, getopt, random, fnmatch, operator, string
import sys,os,os.path,array,getopt,random,types,fnmatch,operator,string
KnownProps=('filename','size','ignore','type','shuffle','reuse','bookmark')
Rules=[
([('filename','~','*.mp3')], {'type':1, 'shuffle':1, 'bookmark':0}),
([('filename','~','*.m4?')], {'type':2, 'shuffle':1, 'bookmark':0}),
([('filename','~','*.m4b')], { 'shuffle':0, 'bookmark':1}),
([('filename','~','*.aa')], {'type':1, 'shuffle':0, 'bookmark':1, 'reuse':1}),
([('filename','~','*.wav')], {'type':4, 'shuffle':0, 'bookmark':0}),
([('filename','~','*.book.???')], { 'shuffle':0, 'bookmark':1}),
([('filename','~','*.announce.???')], { 'shuffle':0, 'bookmark':0}),
([('filename','~','/recycled/*')], {'ignore':1}),
# @formatter:off
KnownProps = ('filename', 'size', 'ignore', 'type', 'shuffle', 'reuse', 'bookmark')
Rules = [
([('filename', '~', '*.mp3')], {'type': 1, 'shuffle': 1, 'bookmark': 0}),
([('filename', '~', '*.m4?')], {'type': 2, 'shuffle': 1, 'bookmark': 0}),
([('filename', '~', '*.m4b')], { 'shuffle': 0, 'bookmark': 1}),
([('filename', '~', '*.aa')], {'type': 1, 'shuffle': 0, 'bookmark': 1, 'reuse': 1}),
([('filename', '~', '*.wav')], {'type': 4, 'shuffle': 0, 'bookmark': 0}),
([('filename', '~', '*.book.???')], { 'shuffle': 0, 'bookmark': 1}),
([('filename', '~', '*.announce.???')], { 'shuffle': 0, 'bookmark': 0}),
([('filename', '~', '/recycled/*')], {'ignore': 1}),
]
# @formatter:on
Options={
"volume":None,
"interactive":False,
"smart":True,
"home":True,
"logging":True,
"reuse":1,
"logfile":"rebuild_db.log.txt",
"rename":False
Options = {
"volume": None,
"interactive": False,
"smart": True,
"home": True,
"logging": True,
"reuse": 1,
"logfile": "rebuild_db.log.txt",
"rename": False
}
domains=[]
total_count=0
KnownEntries={}
domains = []
total_count = 0
KnownEntries = {}
################################################################################
@ -108,21 +112,21 @@ def open_log():
global logfile
if Options['logging']:
try:
logfile=file(Options['logfile'],"w")
logfile = file(Options['logfile'], "w")
except IOError:
logfile=None
logfile = None
else:
logfile=None
logfile = None
def log(line="",newline=True):
def log(line="", newline=True):
global logfile
if newline:
print(line)
line+="\n"
line += "\n"
else:
print(line, end=' ')
line+=" "
line += " "
if logfile:
try:
logfile.write(line)
@ -154,59 +158,62 @@ def filesize(filename):
################################################################################
def MatchRule(props,rule):
def MatchRule(props, rule):
try:
prop,op,ref=props[rule[0]],rule[1],rule[2]
prop, op, ref = props[rule[0]], rule[1], rule[2]
except KeyError:
return False
if rule[1]=='~':
return fnmatch.fnmatchcase(prop.lower(),ref.lower())
elif rule[1]=='=':
return cmp(prop,ref)==0
elif rule[1]=='>':
return cmp(prop,ref)>0
elif rule[1]=='<':
return cmp(prop,ref)<0
if rule[1] == '~':
return fnmatch.fnmatchcase(prop.lower(), ref.lower())
elif rule[1] == '=':
return cmp(prop, ref) == 0
elif rule[1] == '>':
return cmp(prop, ref) > 0
elif rule[1] == '<':
return cmp(prop, ref) < 0
else:
return False
def ParseValue(val):
if len(val)>=2 and ((val[0]=="'" and val[-1]=="'") or (val[0]=='"' and val[-1]=='"')):
if len(val) >= 2 and ((val[0] == "'" and val[-1] == "'") or (val[0] == '"' and val[-1] == '"')):
return val[1:-1]
try:
return int(val)
except ValueError:
return val
def ParseRule(rule):
sep_pos=min([rule.find(sep) for sep in "~=<>" if rule.find(sep)>0])
prop=rule[:sep_pos].strip()
sep_pos = min([rule.find(sep) for sep in "~=<>" if rule.find(sep) > 0])
prop = rule[:sep_pos].strip()
if not prop in KnownProps:
log("WARNING: unknown property `%s'"%prop)
return (prop,rule[sep_pos],ParseValue(rule[sep_pos+1:].strip()))
log("WARNING: unknown property `%s'" % prop)
return (prop, rule[sep_pos], ParseValue(rule[sep_pos + 1:].strip()))
def ParseAction(action):
prop,value=list(map(string.strip,action.split('=',1)))
prop, value = list(map(string.strip, action.split('=', 1)))
if not prop in KnownProps:
log("WARNING: unknown property `%s'"%prop)
return (prop,ParseValue(value))
log("WARNING: unknown property `%s'" % prop)
return (prop, ParseValue(value))
def ParseRuleLine(line):
line=line.strip()
if not(line) or line[0]=="#":
line = line.strip()
if not (line) or line[0] == "#":
return None
try:
# split line into "ruleset: action"
tmp=line.split(":")
ruleset=list(map(string.strip,":".join(tmp[:-1]).split(",")))
actions=dict(list(map(ParseAction,tmp[-1].split(","))))
if len(ruleset)==1 and not(ruleset[0]):
return ([],actions)
tmp = line.split(":")
ruleset = list(map(string.strip, ":".join(tmp[:-1]).split(",")))
actions = dict(list(map(ParseAction, tmp[-1].split(","))))
if len(ruleset) == 1 and not (ruleset[0]):
return ([], actions)
else:
return (list(map(ParseRule,ruleset)),actions)
except OSError: #(ValueError,IndexError,KeyError):
log("WARNING: rule `%s' is malformed, ignoring"%line)
return (list(map(ParseRule, ruleset)), actions)
except OSError: # (ValueError,IndexError,KeyError):
log("WARNING: rule `%s' is malformed, ignoring" % line)
return None
return None
@ -219,29 +226,30 @@ def safe_char(c):
return c
return "_"
def rename_safely(path,name):
base,ext=os.path.splitext(name)
newname=''.join(map(safe_char,base))
if name==newname+ext:
def rename_safely(path, name):
base, ext = os.path.splitext(name)
newname = ''.join(map(safe_char, base))
if name == newname + ext:
return name
if os.path.exists("%s/%s%s"%(path,newname,ext)):
i=0
while os.path.exists("%s/%s_%d%s"%(path,newname,i,ext)):
i+=1
newname+="_%d"%i
newname+=ext
if os.path.exists("%s/%s%s" % (path, newname, ext)):
i = 0
while os.path.exists("%s/%s_%d%s" % (path, newname, i, ext)):
i += 1
newname += "_%d" % i
newname += ext
try:
os.rename("%s/%s"%(path,name),"%s/%s"%(path,newname))
os.rename("%s/%s" % (path, name), "%s/%s" % (path, newname))
except OSError:
pass # don't fail if the rename didn't work
return newname
def write_to_db(filename):
global iTunesSD,domains,total_count,KnownEntries,Rules
global iTunesSD, domains, total_count, KnownEntries, Rules
# set default properties
props={
props = {
'filename': filename,
'size': filesize(filename[1:]),
'ignore': 0,
@ -252,63 +260,65 @@ def write_to_db(filename):
}
# check and apply rules
for ruleset,action in Rules:
if reduce(operator.__and__,[MatchRule(props,rule) for rule in ruleset],True):
for ruleset, action in Rules:
if reduce(operator.__and__, [MatchRule(props, rule) for rule in ruleset], True):
props.update(action)
if props['ignore']: return 0
# retrieve entry from known entries or rebuild it
entry=props['reuse'] and (filename in KnownEntries) and KnownEntries[filename]
entry = props['reuse'] and (filename in KnownEntries) and KnownEntries[filename]
if not entry:
header[29]=props['type']
entry=header.tostring()+ \
"".join([c+"\0" for c in filename[:261]])+ \
"\0"*(525-2*len(filename))
header[29] = props['type']
entry = header.tostring() + \
"".join([c + "\0" for c in filename[:261]]) + \
"\0" * (525 - 2 * len(filename))
# write entry, modifying shuffleflag and bookmarkflag at least
iTunesSD.write(entry[:555]+chr(props['shuffle'])+chr(props['bookmark'])+entry[557])
iTunesSD.write(entry[:555] + chr(props['shuffle']) + chr(props['bookmark']) + entry[557])
if props['shuffle']: domains[-1].append(total_count)
total_count+=1
total_count += 1
return 1
def make_key(s):
if not s: return s
s=s.lower()
s = s.lower()
for i in range(len(s)):
if s[i].isdigit(): break
if not s[i].isdigit(): return s
for j in range(i,len(s)):
for j in range(i, len(s)):
if not s[j].isdigit(): break
if s[j].isdigit(): j+=1
return (s[:i],int(s[i:j]),make_key(s[j:]))
if s[j].isdigit(): j += 1
return (s[:i], int(s[i:j]), make_key(s[j:]))
def key_repr(x):
if type(x)==tuple:
return "%s%d%s"%(x[0],x[1],key_repr(x[2]))
if type(x) == tuple:
return "%s%d%s" % (x[0], x[1], key_repr(x[2]))
else:
return x
def cmp_key(a,b):
if type(a)==tuple and type(b)==tuple:
return cmp(a[0],b[0]) or cmp(a[1],b[1]) or cmp_key(a[2],b[2])
def cmp_key(a, b):
if type(a) == tuple and type(b) == tuple:
return cmp(a[0], b[0]) or cmp(a[1], b[1]) or cmp_key(a[2], b[2])
else:
return cmp(key_repr(a),key_repr(b))
return cmp(key_repr(a), key_repr(b))
def file_entry(path,name,prefix=""):
if not(name) or name[0]==".": return None
fullname="%s/%s"%(path,name)
may_rename=not(fullname.startswith("./iPod_Control")) and Options['rename']
def file_entry(path, name, prefix=""):
if not (name) or name[0] == ".": return None
fullname = "%s/%s" % (path, name)
may_rename = not (fullname.startswith("./iPod_Control")) and Options['rename']
try:
if os.path.islink(fullname):
return None
if os.path.isdir(fullname):
if may_rename: name=rename_safely(path,name)
return (0,make_key(name),prefix+name)
if os.path.splitext(name)[1].lower() in (".mp3",".m4a",".m4b",".m4p",".aa",".wav"):
if may_rename: name=rename_safely(path,name)
return (1,make_key(name),prefix+name)
if may_rename: name = rename_safely(path, name)
return (0, make_key(name), prefix + name)
if os.path.splitext(name)[1].lower() in (".mp3", ".m4a", ".m4b", ".m4p", ".aa", ".wav"):
if may_rename: name = rename_safely(path, name)
return (1, make_key(name), prefix + name)
except OSError:
pass
return None
@ -317,19 +327,19 @@ def file_entry(path,name,prefix=""):
def browse(path, interactive):
global domains
if path[-1]=="/": path=path[:-1]
displaypath=path[1:]
if not displaypath: displaypath="/"
if path[-1] == "/": path = path[:-1]
displaypath = path[1:]
if not displaypath: displaypath = "/"
if interactive:
while 1:
try:
choice=input("include `%s'? [(Y)es, (N)o, (A)ll] "%displaypath)[:1].lower()
choice = input("include `%s'? [(Y)es, (N)o, (A)ll] " % displaypath)[:1].lower()
except EOFError:
raise KeyboardInterrupt
if not choice: continue
if choice in "at": # all/alle/tous/<dontknow>
interactive=0
interactive = 0
break
if choice in "yjos": # yes/ja/oui/si
break
@ -337,71 +347,73 @@ def browse(path, interactive):
return 0
try:
files=[_f for _f in [file_entry(path,name) for name in os.listdir(path)] if _f]
files = [_f for _f in [file_entry(path, name) for name in os.listdir(path)] if _f]
except OSError:
return
if path=="./iPod_Control/Music":
subdirs=[x[2] for x in files if not x[0]]
files=[x for x in files if x[0]]
if path == "./iPod_Control/Music":
subdirs = [x[2] for x in files if not x[0]]
files = [x for x in files if x[0]]
for dir in subdirs:
subpath="%s/%s"%(path,dir)
subpath = "%s/%s" % (path, dir)
try:
files.extend([x for x in [file_entry(subpath,name,dir+"/") for name in os.listdir(subpath)] if x and x[0]])
files.extend(
[x for x in [file_entry(subpath, name, dir + "/") for name in os.listdir(subpath)] if x and x[0]])
except OSError:
pass
files.sort(cmp_key)
count=len([None for x in files if x[0]])
count = len([None for x in files if x[0]])
if count: domains.append([])
real_count=0
real_count = 0
for item in files:
fullname="%s/%s"%(path,item[2])
fullname = "%s/%s" % (path, item[2])
if item[0]:
real_count+=write_to_db(fullname[1:])
real_count += write_to_db(fullname[1:])
else:
browse(fullname,interactive)
browse(fullname, interactive)
if real_count==count:
log("%s: %d files"%(displaypath,count))
if real_count == count:
log("%s: %d files" % (displaypath, count))
else:
log("%s: %d files (out of %d)"%(displaypath,real_count,count))
log("%s: %d files (out of %d)" % (displaypath, real_count, count))
################################################################################
def stringval(i):
if i<0: i+=0x1000000
return "%c%c%c"%(i&0xFF,(i>>8)&0xFF,(i>>16)&0xFF)
if i < 0: i += 0x1000000
return "%c%c%c" % (i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF)
def listval(i):
if i<0: i+=0x1000000
return [i&0xFF,(i>>8)&0xFF,(i>>16)&0xFF]
if i < 0: i += 0x1000000
return [i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF]
def make_playback_state(volume=None):
# I'm not at all proud of this function. Why can't stupid Python make strings
# mutable?!
log("Setting playback state ...",False)
PState=[]
log("Setting playback state ...", False)
PState = []
try:
f=file("iPod_Control/iTunes/iTunesPState","rb")
a=array.array('B')
f = file("iPod_Control/iTunes/iTunesPState", "rb")
a = array.array('B')
a.fromstring(f.read())
PState=a.tolist()
PState = a.tolist()
f.close()
except IOError as EOFError:
del PState[:]
if len(PState)!=21:
PState=listval(29)+[0]*15+listval(1) # volume 29, FW ver 1.0
PState[3:15]=[0]*6+[1]+[0]*5 # track 0, shuffle mode, start of track
if len(PState) != 21:
PState = listval(29) + [0] * 15 + listval(1) # volume 29, FW ver 1.0
PState[3:15] = [0] * 6 + [1] + [0] * 5 # track 0, shuffle mode, start of track
if volume is not None:
PState[:3]=listval(volume)
PState[:3] = listval(volume)
try:
f=file("iPod_Control/iTunes/iTunesPState","wb")
array.array('B',PState).tofile(f)
f = file("iPod_Control/iTunes/iTunesPState", "wb")
array.array('B', PState).tofile(f)
f.close()
except IOError:
log("FAILED.")
@ -411,10 +423,10 @@ def make_playback_state(volume=None):
def make_stats(count):
log("Creating statistics file ...",False)
log("Creating statistics file ...", False)
try:
file("iPod_Control/iTunes/iTunesStats","wb").write(\
stringval(count)+"\0"*3+(stringval(18)+"\xff"*3+"\0"*12)*count)
file("iPod_Control/iTunes/iTunesStats", "wb").write( \
stringval(count) + "\0" * 3 + (stringval(18) + "\xff" * 3 + "\0" * 12) * count)
except IOError:
log("FAILED.")
return 0
@ -427,54 +439,56 @@ def make_stats(count):
def smart_shuffle():
try:
slice_count=max(list(map(len,domains)))
slice_count = max(list(map(len, domains)))
except ValueError:
return []
slices=[[] for x in range(slice_count)]
slice_fill=[0]*slice_count
slices = [[] for x in range(slice_count)]
slice_fill = [0] * slice_count
for d in range(len(domains)):
used=[]
used = []
if not domains[d]: continue
for n in domains[d]:
# find slices where the nearest track of the same domain is far away
metric=[min([slice_count]+[min(abs(s-u),abs(s-u+slice_count),abs(s-u-slice_count)) for u in used]) for s in range(slice_count)]
thresh=old_div((max(metric)+1),2)
farthest=[s for s in range(slice_count) if metric[s]>=thresh]
metric = [
min([slice_count] + [min(abs(s - u), abs(s - u + slice_count), abs(s - u - slice_count)) for u in used])
for s in range(slice_count)]
thresh = old_div((max(metric) + 1), 2)
farthest = [s for s in range(slice_count) if metric[s] >= thresh]
# find emptiest slices
thresh=old_div((min(slice_fill)+max(slice_fill)+1),2)
emptiest=[s for s in range(slice_count) if slice_fill[s]<=thresh if (s in farthest)]
thresh = old_div((min(slice_fill) + max(slice_fill) + 1), 2)
emptiest = [s for s in range(slice_count) if slice_fill[s] <= thresh if (s in farthest)]
# choose one of the remaining candidates and add the track to the chosen slice
s=random.choice(emptiest or farthest)
slices[s].append((n,d))
slice_fill[s]+=1
s = random.choice(emptiest or farthest)
slices[s].append((n, d))
slice_fill[s] += 1
used.append(s)
# shuffle slices and avoid adjacent tracks of the same domain at slice boundaries
seq=[]
last_domain=-1
seq = []
last_domain = -1
for slice in slices:
random.shuffle(slice)
if len(slice)>2 and slice[0][1]==last_domain:
if len(slice) > 2 and slice[0][1] == last_domain:
slice.append(slice.pop(0))
seq+=[x[0] for x in slice]
last_domain=slice[-1][1]
seq += [x[0] for x in slice]
last_domain = slice[-1][1]
return seq
def make_shuffle(count):
random.seed()
if Options['smart']:
log("Generating smart shuffle sequence ...",False)
seq=smart_shuffle()
log("Generating smart shuffle sequence ...", False)
seq = smart_shuffle()
else:
log("Generating shuffle sequence ...",False)
seq=list(range(count))
log("Generating shuffle sequence ...", False)
seq = list(range(count))
random.shuffle(seq)
try:
file("iPod_Control/iTunes/iTunesShuffle","wb").write("".join(map(stringval,seq)))
file("iPod_Control/iTunes/iTunesShuffle", "wb").write("".join(map(stringval, seq)))
except IOError:
log("FAILED.")
return 0
@ -486,13 +500,13 @@ def make_shuffle(count):
def main(dirs):
global header,iTunesSD,total_count,KnownEntries,Rules
log("Welcome to %s, version %s"%(__title__,__version__))
global header, iTunesSD, total_count, KnownEntries, Rules
log("Welcome to %s, version %s" % (__title__, __version__))
log()
try:
f=file("rebuild_db.rules","r")
Rules+=[_f for _f in map(ParseRuleLine,f.read().split("\n")) if _f]
f = file("rebuild_db.rules", "r")
Rules += [_f for _f in map(ParseRuleLine, f.read().split("\n")) if _f]
f.close()
except IOError:
pass
@ -504,40 +518,40 @@ Please make sure that:
(*) the iPod was correctly initialized with iTunes""")
sys.exit(1)
header=array.array('B')
iTunesSD=None
header = array.array('B')
iTunesSD = None
try:
iTunesSD=file("iPod_Control/iTunes/iTunesSD","rb")
header.fromfile(iTunesSD,51)
iTunesSD = file("iPod_Control/iTunes/iTunesSD", "rb")
header.fromfile(iTunesSD, 51)
if Options['reuse']:
iTunesSD.seek(18)
entry=iTunesSD.read(558)
while len(entry)==558:
filename=entry[33::2].split("\0",1)[0]
KnownEntries[filename]=entry
entry=iTunesSD.read(558)
except (IOError,EOFError):
entry = iTunesSD.read(558)
while len(entry) == 558:
filename = entry[33::2].split("\0", 1)[0]
KnownEntries[filename] = entry
entry = iTunesSD.read(558)
except (IOError, EOFError):
pass
if iTunesSD: iTunesSD.close()
if len(header)==51:
if len(header) == 51:
log("Using iTunesSD headers from existing database.")
if KnownEntries:
log("Collected %d entries from existing database."%len(KnownEntries))
log("Collected %d entries from existing database." % len(KnownEntries))
else:
del header[18:]
if len(header)==18:
if len(header) == 18:
log("Using iTunesSD main header from existing database.")
else:
del header[:]
log("Rebuilding iTunesSD main header from scratch.")
header.fromlist([0,0,0,1,6,0,0,0,18]+[0]*9)
header.fromlist([0, 0, 0, 1, 6, 0, 0, 0, 18] + [0] * 9)
log("Rebuilding iTunesSD entry header from scratch.")
header.fromlist([0,2,46,90,165,1]+[0]*20+[100,0,0,1,0,2,0])
header.fromlist([0, 2, 46, 90, 165, 1] + [0] * 20 + [100, 0, 0, 1, 0, 2, 0])
log()
try:
iTunesSD=file("iPod_Control/iTunes/iTunesSD","wb")
iTunesSD = file("iPod_Control/iTunes/iTunesSD", "wb")
header[:18].tofile(iTunesSD)
except IOError:
log("""ERROR: Cannot write to the iPod database file (iTunesSD)!
@ -551,22 +565,22 @@ Please make sure that:
try:
if dirs:
for dir in dirs:
browse("./"+dir,Options['interactive'])
browse("./" + dir, Options['interactive'])
else:
browse(".",Options['interactive'])
log("%d playable files were found on your iPod."%total_count)
browse(".", Options['interactive'])
log("%d playable files were found on your iPod." % total_count)
log()
log("Fixing iTunesSD header.")
iTunesSD.seek(0)
iTunesSD.write("\0%c%c"%(total_count>>8,total_count&0xFF))
iTunesSD.write("\0%c%c" % (total_count >> 8, total_count & 0xFF))
iTunesSD.close()
except IOError:
log("ERROR: Some strange errors occured while writing iTunesSD.")
log(" You may have to re-initialize the iPod using iTunes.")
sys.exit(1)
if make_playback_state(Options['volume'])* \
make_stats(total_count)* \
if make_playback_state(Options['volume']) * \
make_stats(total_count) * \
make_shuffle(total_count):
log()
log("The iPod shuffle database was rebuilt successfully.")
@ -581,7 +595,7 @@ Please make sure that:
def help():
print("Usage: %s [OPTION]... [DIRECTORY]..."%sys.argv[0])
print("Usage: %s [OPTION]... [DIRECTORY]..." % sys.argv[0])
print("""Rebuild iPod shuffle database.
Mandatory arguments to long options are mandatory for short options too.
@ -599,47 +613,49 @@ searched for playable files, unless at least one DIRECTORY is specified.""")
def opterr(msg):
print("parse error:",msg)
print("use `%s -h' to get help"%sys.argv[0])
print("parse error:", msg)
print("use `%s -h' to get help" % sys.argv[0])
sys.exit(1)
def parse_options():
try:
opts,args=getopt.getopt(sys.argv[1:],"hiv:snlfL:r",\
["help","interactive","volume=","nosmart","nochdir","nolog","force","logfile=","rename"])
opts, args = getopt.getopt(sys.argv[1:], "hiv:snlfL:r", \
["help", "interactive", "volume=", "nosmart", "nochdir", "nolog", "force",
"logfile=", "rename"])
except getopt.GetoptError as message:
opterr(message)
for opt,arg in opts:
if opt in ("-h","--help"):
for opt, arg in opts:
if opt in ("-h", "--help"):
help()
sys.exit(0)
elif opt in ("-i","--interactive"):
Options['interactive']=True
elif opt in ("-v","--volume"):
elif opt in ("-i", "--interactive"):
Options['interactive'] = True
elif opt in ("-v", "--volume"):
try:
Options['volume']=int(arg)
Options['volume'] = int(arg)
except ValueError:
opterr("invalid volume")
elif opt in ("-s","--nosmart"):
Options['smart']=False
elif opt in ("-n","--nochdir"):
Options['home']=False
elif opt in ("-l","--nolog"):
Options['logging']=False
elif opt in ("-f","--force"):
Options['reuse']=0
elif opt in ("-L","--logfile"):
Options['logfile']=arg
elif opt in ("-r","--rename"):
Options['rename']=True
elif opt in ("-s", "--nosmart"):
Options['smart'] = False
elif opt in ("-n", "--nochdir"):
Options['home'] = False
elif opt in ("-l", "--nolog"):
Options['logging'] = False
elif opt in ("-f", "--force"):
Options['reuse'] = 0
elif opt in ("-L", "--logfile"):
Options['logfile'] = arg
elif opt in ("-r", "--rename"):
Options['rename'] = True
return args
################################################################################
if __name__=="__main__":
args=parse_options()
if __name__ == "__main__":
args = parse_options()
go_home()
open_log()
try: