A set of utilitaty function for creating commands
This commit is contained in:
0
python/obitools3/apps/__init__.py
Normal file
0
python/obitools3/apps/__init__.py
Normal file
3
python/obitools3/apps/arguments.pxd
Normal file
3
python/obitools3/apps/arguments.pxd
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
cpdef buildArgumentParser(str configname, str softname)
|
61
python/obitools3/apps/arguments.pyx
Normal file
61
python/obitools3/apps/arguments.pyx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 27 mars 2016
|
||||||
|
|
||||||
|
@author: coissac
|
||||||
|
'''
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
from .command import getCommandsList
|
||||||
|
|
||||||
|
class ObiParser(argparse.ArgumentParser):
|
||||||
|
def error(self, message):
|
||||||
|
sys.stderr.write('error: %s\n' % message)
|
||||||
|
self.print_help()
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
cpdef buildArgumentParser(str configname,
|
||||||
|
str softname):
|
||||||
|
parser = ObiParser()
|
||||||
|
|
||||||
|
parser.add_argument('--version', dest='%s:version' % configname,
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='Print the version of %s' % softname)
|
||||||
|
|
||||||
|
parser.add_argument('--log', dest='%s:log' % configname,
|
||||||
|
action='store',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='Create a logfile')
|
||||||
|
|
||||||
|
parser.add_argument('--no-progress', dest='%s:progress' % configname,
|
||||||
|
action='store_false',
|
||||||
|
default=None,
|
||||||
|
help='Do not print the progress bar during analyzes')
|
||||||
|
|
||||||
|
subparsers = parser.add_subparsers(title='subcommands',
|
||||||
|
description='valid subcommands',
|
||||||
|
help='additional help')
|
||||||
|
|
||||||
|
commands = getCommandsList()
|
||||||
|
|
||||||
|
for c in commands:
|
||||||
|
module = commands[c]
|
||||||
|
|
||||||
|
if hasattr(module, "run"):
|
||||||
|
if hasattr(module, "__title__"):
|
||||||
|
sub = subparsers.add_parser(c,help=module.__title__)
|
||||||
|
else:
|
||||||
|
sub = subparsers.add_parser(c)
|
||||||
|
|
||||||
|
if hasattr(module, "addOptions"):
|
||||||
|
module.addOptions(sub)
|
||||||
|
|
||||||
|
sub.set_defaults(**{'%s:module' % configname : module})
|
||||||
|
|
||||||
|
return parser
|
3
python/obitools3/apps/command.pxd
Normal file
3
python/obitools3/apps/command.pxd
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
cdef object loadCommand(str name,loader)
|
44
python/obitools3/apps/command.pyx
Normal file
44
python/obitools3/apps/command.pyx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 27 mars 2016
|
||||||
|
|
||||||
|
@author: coissac
|
||||||
|
'''
|
||||||
|
|
||||||
|
import pkgutil
|
||||||
|
|
||||||
|
from obitools3 import commands
|
||||||
|
|
||||||
|
cdef object loadCommand(str name,loader):
|
||||||
|
'''
|
||||||
|
Load a command module from its name and an ImpLoader
|
||||||
|
|
||||||
|
This function is for internal use
|
||||||
|
|
||||||
|
@param name: name of the module
|
||||||
|
@type name: str
|
||||||
|
@param loader: the module loader
|
||||||
|
@type loader: ImpLoader
|
||||||
|
|
||||||
|
@return the loaded module
|
||||||
|
@rtype: module
|
||||||
|
'''
|
||||||
|
|
||||||
|
module = loader.find_module(name).load_module(name)
|
||||||
|
return module
|
||||||
|
|
||||||
|
def getCommandsList():
|
||||||
|
'''
|
||||||
|
Returns the list of sub-commands available to the main `obi` command
|
||||||
|
|
||||||
|
@return: a dict instance with key corresponding to each command and
|
||||||
|
value corresponding to the module
|
||||||
|
|
||||||
|
@rtype: dict
|
||||||
|
'''
|
||||||
|
|
||||||
|
cdef dict cmds = dict((x[1],loadCommand(x[1],x[0]))
|
||||||
|
for x in pkgutil.iter_modules(commands.__path__)
|
||||||
|
if not x[2])
|
||||||
|
return cmds
|
10
python/obitools3/apps/config.pxd
Normal file
10
python/obitools3/apps/config.pxd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
cpdef str setRootConfigName(str rootname)
|
||||||
|
cpdef str getRootConfigName()
|
||||||
|
|
||||||
|
cdef dict buildDefaultConfiguration(str root_config_name,
|
||||||
|
dict config)
|
||||||
|
|
||||||
|
cpdef dict getConfiguration(str root_config_name,
|
||||||
|
dict config)
|
96
python/obitools3/apps/config.pyx
Normal file
96
python/obitools3/apps/config.pyx
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 27 mars 2016
|
||||||
|
|
||||||
|
@author: coissac
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from .command import getCommandsList
|
||||||
|
from .logging cimport getLogger
|
||||||
|
from .arguments cimport buildArgumentParser
|
||||||
|
|
||||||
|
from obitools3.version import version
|
||||||
|
from _curses import version
|
||||||
|
|
||||||
|
cdef dict __default_config__ = {}
|
||||||
|
|
||||||
|
|
||||||
|
cpdef str setRootConfigName(str rootname):
|
||||||
|
global __default_config__
|
||||||
|
if '__root_config__' in __default_config__:
|
||||||
|
if __default_config__["__root_config__"] in __default_config__:
|
||||||
|
__default_config__[rootname]=__default_config__[__default_config__["__root_config__"]]
|
||||||
|
del __default_config__[__default_config__["__root_config__"]]
|
||||||
|
__default_config__['__root_config__']=rootname
|
||||||
|
return rootname
|
||||||
|
|
||||||
|
cpdef str getRootConfigName():
|
||||||
|
global __default_config__
|
||||||
|
return __default_config__.get('__root_config__',None)
|
||||||
|
|
||||||
|
cdef dict buildDefaultConfiguration(str root_config_name,
|
||||||
|
dict config):
|
||||||
|
global __default_config__
|
||||||
|
|
||||||
|
__default_config__.clear()
|
||||||
|
setRootConfigName(root_config_name)
|
||||||
|
|
||||||
|
__default_config__[root_config_name]=config
|
||||||
|
|
||||||
|
config['version']=version
|
||||||
|
|
||||||
|
commands = getCommandsList()
|
||||||
|
|
||||||
|
for c in commands:
|
||||||
|
module = commands[c]
|
||||||
|
|
||||||
|
assert hasattr(module, "run")
|
||||||
|
|
||||||
|
if hasattr(module, 'default_config'):
|
||||||
|
__default_config__[c]=module.default_config
|
||||||
|
else:
|
||||||
|
__default_config__[c]={}
|
||||||
|
|
||||||
|
return __default_config__
|
||||||
|
|
||||||
|
|
||||||
|
cpdef dict getConfiguration(str root_config_name,
|
||||||
|
dict config):
|
||||||
|
global __default_config__
|
||||||
|
|
||||||
|
if '__done__' in __default_config__:
|
||||||
|
return __default_config__
|
||||||
|
|
||||||
|
|
||||||
|
config = buildDefaultConfiguration(root_config_name,
|
||||||
|
config)
|
||||||
|
|
||||||
|
parser = buildArgumentParser(root_config_name,
|
||||||
|
config[root_config_name]['software'])
|
||||||
|
|
||||||
|
options = vars(parser.parse_args())
|
||||||
|
|
||||||
|
if options['%s:version' % root_config_name]:
|
||||||
|
print("%s - Version %s" % (config[root_config_name]['software'],
|
||||||
|
config[root_config_name]['version']))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
for k in options:
|
||||||
|
section,key = k.split(':')
|
||||||
|
s = config[section]
|
||||||
|
if options[k] is not None:
|
||||||
|
s[key]=options[k]
|
||||||
|
|
||||||
|
if not 'module' in config[root_config_name]:
|
||||||
|
print('\nError: No command specified',file=sys.stderr)
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
getLogger(config)
|
||||||
|
|
||||||
|
config['__done__']=True
|
||||||
|
|
||||||
|
return config
|
3
python/obitools3/apps/logging.pxd
Normal file
3
python/obitools3/apps/logging.pxd
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
cpdef getLogger(dict config)
|
46
python/obitools3/apps/logging.pyx
Normal file
46
python/obitools3/apps/logging.pyx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 27 mars 2016
|
||||||
|
|
||||||
|
@author: coissac
|
||||||
|
'''
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
|
cpdef getLogger(dict config):
|
||||||
|
'''
|
||||||
|
Returns the logger as defined by the command line option
|
||||||
|
or by the config file
|
||||||
|
:param config:
|
||||||
|
'''
|
||||||
|
|
||||||
|
root = config["__root_config__"]
|
||||||
|
|
||||||
|
level = config[root]['loglevel']
|
||||||
|
logfile= config[root]['log']
|
||||||
|
|
||||||
|
rootlogger = logging.getLogger()
|
||||||
|
logFormatter = logging.Formatter("%(asctime)s [%(levelname)-5.5s] %(message)s")
|
||||||
|
|
||||||
|
stderrHandler = logging.StreamHandler(sys.stderr)
|
||||||
|
stderrHandler.setFormatter(logFormatter)
|
||||||
|
|
||||||
|
rootlogger.addHandler(stderrHandler)
|
||||||
|
|
||||||
|
if logfile:
|
||||||
|
fileHandler = logging.FileHandler(logfile)
|
||||||
|
fileHandler.setFormatter(logFormatter)
|
||||||
|
rootlogger.addHandler(fileHandler)
|
||||||
|
|
||||||
|
try:
|
||||||
|
loglevel = getattr(logging, level)
|
||||||
|
except:
|
||||||
|
loglevel = logging.INFO
|
||||||
|
|
||||||
|
rootlogger.setLevel(loglevel)
|
||||||
|
|
||||||
|
config[root]['logger']=rootlogger
|
||||||
|
|
||||||
|
return rootlogger
|
65
python/obitools3/apps/progress.pxd
Normal file
65
python/obitools3/apps/progress.pxd
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
from ..utils cimport str2bytes
|
||||||
|
|
||||||
|
cdef extern from "stdio.h":
|
||||||
|
struct FILE
|
||||||
|
int fprintf(FILE *stream, char *format, ...)
|
||||||
|
FILE* stderr
|
||||||
|
ctypedef unsigned int off_t "unsigned long long"
|
||||||
|
|
||||||
|
cdef extern from "unistd.h":
|
||||||
|
int fsync(int fd);
|
||||||
|
|
||||||
|
cdef extern from "time.h":
|
||||||
|
struct tm :
|
||||||
|
int tm_yday
|
||||||
|
int tm_hour
|
||||||
|
int tm_min
|
||||||
|
int tm_sec
|
||||||
|
|
||||||
|
enum: CLOCKS_PER_SEC
|
||||||
|
|
||||||
|
ctypedef int time_t
|
||||||
|
ctypedef int clock_t
|
||||||
|
ctypedef int suseconds_t
|
||||||
|
|
||||||
|
struct timeval:
|
||||||
|
time_t tv_sec # seconds */
|
||||||
|
suseconds_t tv_usec # microseconds */
|
||||||
|
|
||||||
|
|
||||||
|
struct timezone :
|
||||||
|
int tz_minuteswest; # minutes west of Greenwich
|
||||||
|
int tz_dsttime; # type of DST correction
|
||||||
|
|
||||||
|
|
||||||
|
int gettimeofday(timeval *tv, timezone *tz)
|
||||||
|
|
||||||
|
|
||||||
|
tm *gmtime_r(time_t *clock, tm *result)
|
||||||
|
time_t time(time_t *tloc)
|
||||||
|
clock_t clock()
|
||||||
|
|
||||||
|
cdef class ProgressBar:
|
||||||
|
cdef off_t maxi
|
||||||
|
cdef clock_t starttime
|
||||||
|
cdef clock_t lasttime
|
||||||
|
cdef clock_t tickcount
|
||||||
|
cdef int freq
|
||||||
|
cdef int cycle
|
||||||
|
cdef int arrow
|
||||||
|
cdef int lastlog
|
||||||
|
cdef bint ontty
|
||||||
|
cdef int fd
|
||||||
|
|
||||||
|
cdef bytes head
|
||||||
|
cdef char *chead
|
||||||
|
|
||||||
|
cdef object logger
|
||||||
|
|
||||||
|
cdef char *wheel
|
||||||
|
cdef char *spaces
|
||||||
|
cdef char* diese
|
||||||
|
|
||||||
|
cdef clock_t clock(self)
|
138
python/obitools3/apps/progress.pyx
Normal file
138
python/obitools3/apps/progress.pyx
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#cython: language_level=3
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 27 mars 2016
|
||||||
|
|
||||||
|
@author: coissac
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from ..utils cimport bytes2str
|
||||||
|
|
||||||
|
cdef class ProgressBar:
|
||||||
|
cdef clock_t clock(self):
|
||||||
|
cdef clock_t t
|
||||||
|
cdef timeval tp
|
||||||
|
cdef clock_t s
|
||||||
|
|
||||||
|
<void> gettimeofday(&tp,NULL)
|
||||||
|
s = <clock_t> (<double> tp.tv_usec * 1.e-6 * <double> CLOCKS_PER_SEC)
|
||||||
|
t = tp.tv_sec * CLOCKS_PER_SEC + s
|
||||||
|
|
||||||
|
return t
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
off_t maxi,
|
||||||
|
dict config,
|
||||||
|
str head="",
|
||||||
|
double seconde=0.1):
|
||||||
|
self.starttime = self.clock()
|
||||||
|
self.lasttime = self.starttime
|
||||||
|
self.tickcount = <clock_t> (seconde * CLOCKS_PER_SEC)
|
||||||
|
self.freq = 1
|
||||||
|
self.cycle = 0
|
||||||
|
self.arrow = 0
|
||||||
|
self.lastlog = 0
|
||||||
|
|
||||||
|
self.ontty = sys.stderr.isatty()
|
||||||
|
|
||||||
|
if (maxi<=0):
|
||||||
|
maxi=1
|
||||||
|
|
||||||
|
self.maxi = maxi
|
||||||
|
self.head = str2bytes(head)
|
||||||
|
self.chead= self.head
|
||||||
|
|
||||||
|
|
||||||
|
self.logger=config[config["__root_config__"]]["logger"]
|
||||||
|
self.wheel = '|/-\\'
|
||||||
|
self.spaces=' ' \
|
||||||
|
' ' \
|
||||||
|
' ' \
|
||||||
|
' ' \
|
||||||
|
' '
|
||||||
|
self.diese ='##########' \
|
||||||
|
'##########' \
|
||||||
|
'##########' \
|
||||||
|
'##########' \
|
||||||
|
'##########'
|
||||||
|
|
||||||
|
def __call__(self,object pos):
|
||||||
|
cdef off_t ipos
|
||||||
|
cdef clock_t elapsed
|
||||||
|
cdef clock_t newtime
|
||||||
|
cdef clock_t delta
|
||||||
|
cdef clock_t more
|
||||||
|
cdef double percent
|
||||||
|
cdef tm remain
|
||||||
|
cdef int days,hour,minu,sec
|
||||||
|
cdef off_t fraction
|
||||||
|
cdef int twentyth
|
||||||
|
|
||||||
|
self.cycle+=1
|
||||||
|
|
||||||
|
if self.cycle % self.freq == 0:
|
||||||
|
self.cycle=1
|
||||||
|
newtime = self.clock()
|
||||||
|
delta = newtime - self.lasttime
|
||||||
|
self.lasttime = newtime
|
||||||
|
elapsed = newtime - self.starttime
|
||||||
|
# print(" ",delta,elapsed,elapsed/CLOCKS_PER_SEC,self.tickcount)
|
||||||
|
|
||||||
|
if delta < self.tickcount / 5 :
|
||||||
|
self.freq*=2
|
||||||
|
elif delta > self.tickcount * 5 and self.freq>1:
|
||||||
|
self.freq/=2
|
||||||
|
|
||||||
|
|
||||||
|
if callable(pos):
|
||||||
|
ipos=pos()
|
||||||
|
else:
|
||||||
|
ipos=pos
|
||||||
|
|
||||||
|
if ipos==0:
|
||||||
|
ipos=1
|
||||||
|
|
||||||
|
percent = <double>ipos/<double>self.maxi
|
||||||
|
more = <time_t>((<double>elapsed / percent * (1. - percent))/CLOCKS_PER_SEC)
|
||||||
|
<void>gmtime_r(&more, &remain)
|
||||||
|
days = remain.tm_yday
|
||||||
|
hour = remain.tm_hour
|
||||||
|
minu = remain.tm_min
|
||||||
|
sec = remain.tm_sec
|
||||||
|
|
||||||
|
if self.ontty:
|
||||||
|
fraction=<int>(percent * 50.)
|
||||||
|
self.arrow=(self.arrow+1) % 4
|
||||||
|
self.diese[fraction]=0
|
||||||
|
self.spaces[50 - fraction]=0
|
||||||
|
|
||||||
|
if days:
|
||||||
|
<void>fprintf(stderr,b'\r%s %5.1f %% |%s%c%s] remain : %d days %02d:%02d:%02d',
|
||||||
|
self.chead,
|
||||||
|
percent*100,
|
||||||
|
self.diese,self.wheel[self.arrow],self.spaces,
|
||||||
|
days,hour,minu,sec)
|
||||||
|
else:
|
||||||
|
<void>fprintf(stderr,b'\r%s %5.1f %% |%s%c%s] remain : %02d:%02d:%02d',
|
||||||
|
self.chead,
|
||||||
|
percent*100.,
|
||||||
|
self.diese,self.wheel[self.arrow],self.spaces,
|
||||||
|
hour,minu,sec)
|
||||||
|
self.diese[fraction]=b'#'
|
||||||
|
self.spaces[50 - fraction]=b' '
|
||||||
|
|
||||||
|
twentyth = int(percent * 20)
|
||||||
|
if twentyth != self.lastlog:
|
||||||
|
|
||||||
|
if self.ontty:
|
||||||
|
<void>fprintf(stderr,b'\n')
|
||||||
|
|
||||||
|
self.logger.info('%s %5.1f %% remain : %02d:%02d:%02d' % (
|
||||||
|
bytes2str(self.head),
|
||||||
|
percent*100.,
|
||||||
|
hour,minu,sec))
|
||||||
|
self.lastlog=twentyth
|
||||||
|
else:
|
||||||
|
self.cycle+=1
|
||||||
|
|
Reference in New Issue
Block a user