added coniuga.py (with deps) to doc/ - contains usage paths for ffmpeg -map that might be implemented one day
This commit is contained in:
parent
ae18e7a6ef
commit
65b0fe6144
2 changed files with 1333 additions and 0 deletions
366
doc/ellib.py
Executable file
366
doc/ellib.py
Executable file
|
@ -0,0 +1,366 @@
|
|||
#! /bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os, pickle, re, sys, time, traceback
|
||||
|
||||
__version = '1.9.2'
|
||||
|
||||
class CmdParser:
|
||||
class config:
|
||||
pass
|
||||
def __init__(self, mapping, source = sys.argv[1:]):
|
||||
# pools for variable quadruples
|
||||
p_long = []
|
||||
p_short = []
|
||||
p_type = []
|
||||
p_plural = {}
|
||||
p_default = {}
|
||||
# Legacy checks for pre-1.7 or pre-1.9 programs -- it's a CRAP, so i had them neutered :]
|
||||
#l_mapping = len(mapping)
|
||||
#if l_mapping%3 == 0 and l_mapping%4 != 0:
|
||||
#maptype = 3
|
||||
#say("ellib.CmdParser: Pre-1.7 or 1.9 program detected, running in legacy mode", timestamp = True, icon = "DBG")
|
||||
#else:
|
||||
#maptype = 5
|
||||
maptype = 5
|
||||
|
||||
for i in range(0, len(mapping), maptype):
|
||||
p_long.append(mapping[i])
|
||||
p_short.append(mapping[i+1])
|
||||
p_type.append(mapping[i+2])
|
||||
p_plural[mapping[i]] = mapping[i+3]
|
||||
p_default[mapping[i]] = mapping[i+4]
|
||||
|
||||
# Switches and targets arrays.
|
||||
self.switches = {}
|
||||
for name in p_long:
|
||||
if p_plural[name]:
|
||||
self.switches[name] = []
|
||||
else:
|
||||
self.switches[name] = None
|
||||
self.targets = []
|
||||
self.errors = []
|
||||
|
||||
|
||||
# Behold, the Parser !!!
|
||||
delka = len(source)
|
||||
mapa = range(delka)
|
||||
for i in range(delka):
|
||||
if i in mapa:
|
||||
arg = source[i]
|
||||
if arg[:2] == '--' and arg[:5] != '--no-':
|
||||
if arg[2:] in p_long:
|
||||
if p_type[p_long.index(arg[2:])] == 0:
|
||||
if p_plural[arg[2:]]:
|
||||
self.switches[arg[2:]].append(True)
|
||||
else:
|
||||
self.switches[arg[2:]] = True
|
||||
else:
|
||||
try:
|
||||
if p_plural[arg[2:]]:
|
||||
self.switches[arg[2:]].append(source[i+1])
|
||||
else:
|
||||
self.switches[arg[2:]] = source[i+1]
|
||||
mapa.remove(i+1)
|
||||
except:
|
||||
self.errors.append(arg)
|
||||
else:
|
||||
self.errors.append(arg)
|
||||
|
||||
elif arg[:5] == '--no-':
|
||||
if arg[5:] in p_long:
|
||||
if p_type[p_long.index(arg[5:])] == 0:
|
||||
if p_plural[arg[5:]]:
|
||||
self.switches[arg[5:]].append(False)
|
||||
else:
|
||||
self.switches[arg[5:]] = False
|
||||
else:
|
||||
self.errors.append(arg)
|
||||
|
||||
elif arg[0] in ['-', '+']:
|
||||
for x in arg[1:]:
|
||||
if x in p_short:
|
||||
longname = p_long[p_short.index(x)]
|
||||
if p_type[p_short.index(x)] == 0:
|
||||
if arg[0] == '-':
|
||||
value = False
|
||||
else:
|
||||
value = True
|
||||
if p_plural[longname]:
|
||||
self.switches[longname].append(value)
|
||||
else:
|
||||
self.switches[longname] = value
|
||||
else:
|
||||
try:
|
||||
if p_plural[longname]:
|
||||
self.switches[longname].append(source[i+1])
|
||||
else:
|
||||
self.switches[longname] = source[i+1]
|
||||
mapa.remove(i+1)
|
||||
except:
|
||||
self.errors.append(arg[0]+x)
|
||||
else:
|
||||
self.errors.append(arg[0]+x)
|
||||
|
||||
else:
|
||||
self.targets.append(arg)
|
||||
|
||||
# Look for empty fields and fill them with default values if possible
|
||||
for name in self.switches:
|
||||
if name in p_default.keys() and p_default[name] != None and self.switches[name] in [[], None]:
|
||||
if type(p_default[name]) == list:
|
||||
self.switches[name] = p_default[name]
|
||||
else:
|
||||
if p_plural[name]:
|
||||
self.switches[name] = [p_default[name]]
|
||||
else:
|
||||
self.switches[name] = p_default[name]
|
||||
# Fill the self.switches dictionary into self.config variables for easier access
|
||||
name2 = name.replace(' ', '_').replace('-', '_').replace('+', '_')
|
||||
setattr(self.config, name2, self.switches[name])
|
||||
|
||||
# if there's a "--debug" somewhere on the line, run a command dump
|
||||
if '--debug' in source:
|
||||
_debug = True
|
||||
say("Command dump", 1)
|
||||
for name in self.switches:
|
||||
say("%s: %s" %(name, self.switches[name]))
|
||||
say("Command dump", 2)
|
||||
|
||||
class Db:
|
||||
"""Třída velmi špatné databáze:
|
||||
* při inicializaci se vytvoří databáze se jménem name, pokud neexistuje. Otevře databázi.
|
||||
* metoda read() - přečte databázi
|
||||
* metoda write() - zapíše (přepíše) databázi
|
||||
* metoda remove() - odstraní řádek
|
||||
"""
|
||||
def __init__(self, filename):
|
||||
"""Otevře databázi, pokud neexistuje, vytvoří ji."""
|
||||
self.filename = filename
|
||||
if os.path.isfile(self.filename):
|
||||
try: file = open(self.filename, 'r+')
|
||||
except IOError: file = open(self.filename, 'r')
|
||||
else:
|
||||
say("Vytvářím databázi %s \r" %(self.filename), 1, 1)
|
||||
file = open(self.filename, 'w')
|
||||
file.write('None')
|
||||
say("Databáze %s vytvořena." %(self.filename), 2)
|
||||
file.close()
|
||||
try: file = open(self.filename, 'r+')
|
||||
except IOError: file = open(self.filename, 'r')
|
||||
self.file = file
|
||||
|
||||
def read(self):
|
||||
"""Low level funkce; vrátí databázi"""
|
||||
self.file.seek(0)
|
||||
try: return pickle.load(self.file)
|
||||
except:
|
||||
return []
|
||||
|
||||
def write(self, object):
|
||||
"""Low level funkce; zapíše databázi"""
|
||||
self.file.seek(0)
|
||||
retval = pickle.dump(object, self.file)
|
||||
self.file.flush()
|
||||
return retval
|
||||
|
||||
def remove(self, ID):
|
||||
"""Odstraní řádek z databáze."""
|
||||
database = self.read()
|
||||
del database[ID]
|
||||
return self.write(database)
|
||||
|
||||
def add(self, line):
|
||||
"""Zapíše řádek do databáze"""
|
||||
database = self.read()
|
||||
database.append(line)
|
||||
return self.write(database)
|
||||
|
||||
class Help:
|
||||
def __init__(self, rawtext):
|
||||
self.rawtext = rawtext+'\n[[' # a kinky workaround indeed :)
|
||||
self.blocks = {}
|
||||
self.order = []
|
||||
self.mkindex()
|
||||
def mkindex(self):
|
||||
chunk = re.findall('\[\[(.+?)\]\]\n(.+?)(?=\[\[)', self.rawtext, re.S)
|
||||
for section in chunk:
|
||||
if len(section) == 2: # caption and text
|
||||
self.order.append(section[0])
|
||||
self.blocks[section[0]] = section[1]
|
||||
else:
|
||||
say("Help section is of wrong lenght, please report a bug (provide the original help text if possible)", timestamp = True, icon = "<Cr>FAIL<C/>")
|
||||
def __call__(self, caption = None):
|
||||
if caption in self.blocks.keys():
|
||||
return style(self.blocks[caption])
|
||||
else:
|
||||
tosend = ""
|
||||
for cap in self.order:
|
||||
tosend += "[<CB>%s<C/>]\n%s" %(cap, self.blocks[cap])
|
||||
return style(tosend)
|
||||
def help(self, caption = None):
|
||||
return self.__call__(caption)
|
||||
|
||||
# output engine
|
||||
colortags = {
|
||||
'<Cg>': '\x1b[32;01m',
|
||||
'<Cy>': '\x1b[33;01m',
|
||||
'<Cr>': '\x1b[31;01m',
|
||||
'<Cb>': '\x1b[34;01m',
|
||||
'<CB>': '\x1b[01m',
|
||||
'<C/>': '\x1b[39;49;00m'
|
||||
}
|
||||
|
||||
badchars = {
|
||||
'\"': '\\"',
|
||||
'\x00': '',
|
||||
'/': '-'
|
||||
}
|
||||
|
||||
def charfilter(text, sada = badchars):
|
||||
for badchar in sada.keys():
|
||||
text = text.replace(badchar, sada[badchar])
|
||||
return text
|
||||
|
||||
# R.I.P, you served us well. May this line make us remember you for ages.
|
||||
# Eram, non sum, non misero...
|
||||
#def style(text):
|
||||
#return re.compile('<C.>').sub(lambda text: colortags[text.group()], text)
|
||||
|
||||
def style(text):
|
||||
tags = re.findall('<C.>', text)
|
||||
for tag in tags:
|
||||
try:
|
||||
text = text.replace(tag, colortags[tag])
|
||||
except KeyError:
|
||||
pass
|
||||
return text
|
||||
|
||||
def say(text, mode = 0, breakline = True, timestamp = False, icon = ""):
|
||||
if isinstance(text, unicode) and sys.stdout.encoding:
|
||||
text = text.encode(sys.stdout.encoding)
|
||||
text = str(text)
|
||||
if _debug:
|
||||
timestamp = True
|
||||
icons = _icons_debug
|
||||
else:
|
||||
icons = _icons
|
||||
if mode in range(1, len(icons)) and not icon:
|
||||
icon = icons[mode]
|
||||
elif not icon:
|
||||
icon = icons[0]
|
||||
if breakline == 1:
|
||||
br = '\n'
|
||||
else:
|
||||
br = ''
|
||||
if timestamp:
|
||||
text = style(time.strftime('%Y-%m-%d %H:%M:%S ')+icon+' -- '+text)+br
|
||||
else:
|
||||
text = style(icon+' '+text)+br
|
||||
if _log: log(text)
|
||||
sys.stdout.write(text)
|
||||
sys.stdout.flush()
|
||||
|
||||
def countdown(units, text = "", secs = 1):
|
||||
ticks = range(units)
|
||||
ticks.reverse()
|
||||
try:
|
||||
for i in ticks:
|
||||
say(text+str(i+1)+' \r', 1, 0)
|
||||
time.sleep(secs)
|
||||
say(text+'0 ', 2)
|
||||
return True
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
say(text+'0 ', 3)
|
||||
return False
|
||||
|
||||
def log(text, logfile = None):
|
||||
if not logfile:
|
||||
logfile = _logfile
|
||||
if not text:
|
||||
return False
|
||||
if text[-1] != '\n':
|
||||
text += '\n'
|
||||
fd = open(logfile, 'a')
|
||||
fd.write(text)
|
||||
fd.close()
|
||||
|
||||
def join(array, separator=' '):
|
||||
return separator.join(array)
|
||||
|
||||
def logger(status, prefix = '.'):
|
||||
global _log, _logfile
|
||||
_prefix = prefix
|
||||
|
||||
if status:
|
||||
_log = True
|
||||
# Check if prefix is a directory: if it's a file, log into ".", if it doesn't exist, create it.
|
||||
if not os.path.isdir(_prefix) and os.path.exists(_prefix):
|
||||
_prefix = '.'
|
||||
elif not os.path.exists(_prefix):
|
||||
os.mkdir(_prefix)
|
||||
_logfile = _prefix + '/' + time.strftime('%Y-%m-%d %H:%M:%S')+'.log'
|
||||
if prefix != _prefix: say("%s exists, but is not a directory." %(prefix), 3)
|
||||
say("Logging into %s" %(_logfile), 1)
|
||||
else:
|
||||
say("Logging into %s" %(_logfile), 2)
|
||||
_log = False
|
||||
|
||||
class File:
|
||||
def __init__(self, name, mode = 'r'):
|
||||
self.name = name
|
||||
self.mode = mode
|
||||
self.fd = open(name, mode)
|
||||
self.data = ''
|
||||
def read(self):
|
||||
self.data = self.fd.read()
|
||||
def write(self):
|
||||
self.fd.write(self.data)
|
||||
def close(self):
|
||||
self.fd.close()
|
||||
|
||||
def coredump(loc):
|
||||
import code
|
||||
c = code.InteractiveConsole(loc)
|
||||
c.interact()
|
||||
|
||||
class Autoloader:
|
||||
def __init__(self):
|
||||
self.original_handler = sys.excepthook
|
||||
|
||||
def register(self, deact=False):
|
||||
if not deact:
|
||||
sys.excepthook = self
|
||||
else:
|
||||
sys.excepthook = self.original_handler
|
||||
|
||||
def __call__(self, exctype, value, trace):
|
||||
if exctype == NameError:
|
||||
module_name = charfilter(value.args[0], {"name '": "", "' is not defined": ""})
|
||||
#retval = _exec("import %s" % module_name, trace)
|
||||
|
||||
command_locals = trace.tb_frame.f_locals
|
||||
command_globals = trace.tb_frame.f_globals
|
||||
try: # retval relates to import success only
|
||||
exec "import %s" % module_name in command_locals, command_globals
|
||||
retval = True
|
||||
say("Autoloaded module <Cg>%s<C/>" %(module_name), timestamp=True, icon="INFO")
|
||||
exec trace.tb_frame.f_code in command_locals, command_globals
|
||||
retval = True
|
||||
except ImportError:
|
||||
retval = False
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
if exctype != NameError or not retval:
|
||||
traceback.print_exception(exctype, value, trace)
|
||||
|
||||
autoloader = Autoloader()
|
||||
|
||||
# Ellib setup
|
||||
|
||||
_debug = False
|
||||
_log = False
|
||||
_icons = [" ", ">>> ", "<Cg> * <C/>", "<Cr> * <C/>"]
|
||||
_icons_debug = ["INFO", "<CB>EXEC<C/>", "<Cg>DONE<C/>", "<Cr>FAIL<C/>"]
|
||||
_logfile = time.strftime('%Y-%m-%d %H:%M:%S')+".log"
|
Loading…
Add table
Add a link
Reference in a new issue