initial commit
This commit is contained in:
304
lib/console.py
Normal file
304
lib/console.py
Normal file
@@ -0,0 +1,304 @@
|
||||
from . import utils
|
||||
import os
|
||||
import traceback
|
||||
|
||||
class console():
|
||||
def __init__(self, name='base'):
|
||||
self.name = name
|
||||
self.hint = '$ '
|
||||
self.exit_cmd = ['exit', 'quit', 'bye']
|
||||
self.exit_info = 'Bye~'
|
||||
self.commands = {}
|
||||
self.alias = {}
|
||||
self.warn_level = 4
|
||||
self.exit_flag = False
|
||||
self.debug = True
|
||||
self.platform = utils.detect_platform()
|
||||
self.is_child = False
|
||||
self.father = None
|
||||
|
||||
self.regist_internal_command()
|
||||
|
||||
def get_hint(self):
|
||||
if self.platform == 'Linux':
|
||||
hint = '\033[0;33m({0})\033[0;31m{1}\033[0m'.format(self.name, self.hint)
|
||||
else:
|
||||
hint = '({0}){1}'.format(self.name, self.hint)
|
||||
return hint
|
||||
|
||||
def regist_internal_command(self):
|
||||
self.regist(
|
||||
'help',
|
||||
action=self.command_help,
|
||||
alias=['h'],
|
||||
help_info='display this help info.',
|
||||
kind='sys'
|
||||
)
|
||||
self.regist(
|
||||
'exit',
|
||||
action=self.command_exit_console,
|
||||
alias=['quit','bye'],
|
||||
help_info='exit current console.',
|
||||
kind='sys'
|
||||
)
|
||||
self.regist(
|
||||
'cls',
|
||||
action=self.command_clear_screen,
|
||||
alias=['clear', 'clc'],
|
||||
help_info='clear screen.',
|
||||
kind='sys'
|
||||
)
|
||||
self.regist(
|
||||
'alias',
|
||||
action=self.command_alias,
|
||||
help_info='display alias info or create new alias.',
|
||||
kind='sys'
|
||||
)
|
||||
self.regist(
|
||||
'os',
|
||||
action=self.command_os,
|
||||
help_info='run a system command.',
|
||||
kind='sys'
|
||||
)
|
||||
|
||||
|
||||
def translate_command(self, command):
|
||||
while command in self.alias and command not in self.commands:
|
||||
command = self.alias[command]
|
||||
return command
|
||||
|
||||
def find_equal_command(self, command, ret_type = str, ignored = []):
|
||||
finished = []
|
||||
new = []
|
||||
|
||||
cmds = [command]
|
||||
while len(finished) != len(cmds):
|
||||
# find child
|
||||
if command in self.alias:
|
||||
if self.alias[command] not in cmds:
|
||||
cmds.append(self.alias[command])
|
||||
# find fathers
|
||||
for al in self.alias:
|
||||
if self.alias[al] == command:
|
||||
if al not in cmds:
|
||||
cmds.append(al)
|
||||
# found finished.
|
||||
finished.append(command)
|
||||
for cmd in cmds:
|
||||
if cmd not in finished:
|
||||
command = cmd
|
||||
|
||||
|
||||
if ret_type is str:
|
||||
finished = utils.list2csv(finished)
|
||||
return finished
|
||||
|
||||
|
||||
|
||||
def get_alias(self, command, ret_type=str):
|
||||
alias = []
|
||||
for al in self.alias:
|
||||
if self.alias[al] == command:
|
||||
alias.append(al)
|
||||
|
||||
if ret_type is str:
|
||||
alias = utils.list2csv(alias)
|
||||
|
||||
return alias
|
||||
|
||||
def command_exist(self, command):
|
||||
if command in self.commands or command in self.alias:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def add_alias(self, command, alias):
|
||||
if self.command_exist(alias):
|
||||
if warn_level >= 3:
|
||||
print('Alias {0} will not be added since already used'.format(al))
|
||||
else:
|
||||
self.alias[alias] = command
|
||||
|
||||
# kind: standard or shared
|
||||
# standard: help info will be displayed
|
||||
# shared: help info will not be displayed in sub command.
|
||||
def regist(self, command, action, alias=None, help_info='no help provided.', kind='standard'):
|
||||
if type(action) == console:
|
||||
action.is_child = True
|
||||
action.father = self
|
||||
exist = self.command_exist(command)
|
||||
if exist:
|
||||
if self.warn_level >=3:
|
||||
print('Command {0} will not be added sinece already exist.'.format(command))
|
||||
return
|
||||
|
||||
if type(alias) is list:
|
||||
for al in alias:
|
||||
self.add_alias(command, al)
|
||||
elif type(alias) is str:
|
||||
self.add_alias(command, alias)
|
||||
elif alias is None:
|
||||
pass
|
||||
else:
|
||||
if self.warn_level > 3:
|
||||
print('Unknown alias type, no alias will be added.')
|
||||
self.commands[command] = {}
|
||||
self.commands[command]['action'] = action
|
||||
self.commands[command]['help'] = help_info
|
||||
self.commands[command]['kind'] = kind
|
||||
|
||||
def handle_command(self, command, args):
|
||||
if command in self.commands:
|
||||
act = self.commands[command]['action']
|
||||
try:
|
||||
act(args)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
print('Exception occured while processing command \"{0} {1}\".'.format(command, args))
|
||||
print('More information are shown below.\n', traceback.format_exc())
|
||||
else:
|
||||
print('Unknown command \"{0}\"'.format(command))
|
||||
|
||||
# seperate command and its args.
|
||||
def parse_command(self, string):
|
||||
string += ' '
|
||||
length = len(string)
|
||||
command_end = 0
|
||||
parse_start = False
|
||||
for i in range(length):
|
||||
blank = utils.is_blank(string[i])
|
||||
if not blank:
|
||||
parse_start=True
|
||||
if parse_start and blank:
|
||||
command_end = i
|
||||
break
|
||||
|
||||
command = string[:command_end]
|
||||
command = utils.remove_blank_in_endpoint(command)
|
||||
args = utils.remove_blank_in_endpoint(string[command_end:])
|
||||
return command, args
|
||||
|
||||
def parse(self, string):
|
||||
command, args = self.parse_command(string)
|
||||
exitsted_commands = []
|
||||
while command in self.alias:
|
||||
if command not in exitsted_commands:
|
||||
exitsted_commands.append(command)
|
||||
command = self.alias[command]
|
||||
string = command + ' ' + args
|
||||
command, args = self.parse_command(string)
|
||||
else:
|
||||
break
|
||||
|
||||
return command, args
|
||||
|
||||
|
||||
def show_help_info(self, command, prefix, indent, depth=0):
|
||||
command = self.translate_command(command)
|
||||
action = self.commands[command]['action']
|
||||
kind = self.commands[command]['kind']
|
||||
if kind == 'sys' and depth > 0:
|
||||
return
|
||||
alias = self.get_alias(command, ret_type=str)
|
||||
if alias != '':
|
||||
print('{0}{1}({2}):'.format(prefix, command, alias))
|
||||
else:
|
||||
print('{0}{1}:'.format(prefix, command))
|
||||
print('{0}{1}{2}'.format(prefix, indent, self.commands[command]['help']))
|
||||
if type(action) == console:
|
||||
action.command_help('', prefix=prefix+indent, indent=indent, depth=depth+1)
|
||||
|
||||
def debug_log(self, command, args):
|
||||
if self.debug:
|
||||
print('command:[{0}] args:[{1}]'.format(command, args))
|
||||
|
||||
def command_exit_console(self, args):
|
||||
if not self.is_child:
|
||||
print(self.exit_info)
|
||||
self.exit_flag = True
|
||||
|
||||
def command_clear_screen(self, args):
|
||||
if self.platform == 'Windows':
|
||||
os.system('cls')
|
||||
elif self.platform == 'Linux':
|
||||
os.system('clear')
|
||||
return False
|
||||
|
||||
def command_help(self, args, prefix = '', indent=' ', depth=0):
|
||||
command, args = self.parse_command(args)
|
||||
if command is not "":
|
||||
if self.command_exist(command):
|
||||
self.show_help_info(command, prefix, indent, depth)
|
||||
else:
|
||||
print('Unknown command \"{0}\"'.format(command))
|
||||
else:
|
||||
for command in self.commands:
|
||||
self.show_help_info(command, prefix, indent, depth)
|
||||
|
||||
def command_alias(self, args):
|
||||
alias_parse = args.split('=')
|
||||
if len(alias_parse) == 2:
|
||||
alias = utils.remove_blank_in_endpoint(alias_parse[0])
|
||||
command = utils.remove_blank_in_endpoint(alias_parse[1])
|
||||
if command is not '':
|
||||
self.alias[alias]=command
|
||||
else:
|
||||
del self.alias[alias]
|
||||
elif args == '':
|
||||
for alias in self.alias:
|
||||
print('{0}={1}'.format(alias, self.alias[alias]))
|
||||
elif len(alias_parse) == 1:
|
||||
if args in self.alias:
|
||||
print('{0}={1}'.format(args, self.alias[args]))
|
||||
equal_alias = self.find_equal_command(args)
|
||||
if equal_alias != '':
|
||||
print('Hint: {0} are all equivalent.'.format(equal_alias))
|
||||
elif args in self.commands:
|
||||
als = self.get_alias(args, ret_type=str)
|
||||
if als == '':
|
||||
print('command {0} has no alias.'.format(args))
|
||||
else:
|
||||
print('command {0} is aliased as {1}'.format(args, als))
|
||||
equal_alias = self.find_equal_command(args)
|
||||
if equal_alias != '' and equal_alias != args:
|
||||
print('Hint: {0} are all equivalent.'.format(equal_alias))
|
||||
else:
|
||||
print('No alias \"{0}\" found.'.format(args))
|
||||
else:
|
||||
print('Syntax error, command not understood.')
|
||||
|
||||
def command_os(self, args):
|
||||
if args == '':
|
||||
print('please specify os command')
|
||||
else:
|
||||
os.system(args)
|
||||
|
||||
def execute(self, string):
|
||||
command, args = self.parse(string)
|
||||
if command is not "":
|
||||
self.handle_command(command, args)
|
||||
|
||||
def __call__(self, args):
|
||||
if args != '':
|
||||
self.execute(args)
|
||||
else:
|
||||
self.exit_flag=False
|
||||
self.interactive()
|
||||
|
||||
def interactive(self):
|
||||
while not self.exit_flag:
|
||||
try:
|
||||
input_str = input(self.get_hint())
|
||||
self.execute(input_str)
|
||||
except(KeyboardInterrupt):
|
||||
print('')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
con = console()
|
||||
con_sub = console()
|
||||
con_sub_sub = console()
|
||||
con_sub.regist('test_subsubcommand', con_sub_sub, alias='tss', help_info='A sub command.')
|
||||
con.regist('test_subcommand', con_sub, alias='ts', help_info='A sub command.')
|
||||
con.interactive()
|
||||
127
lib/parallel.py
Normal file
127
lib/parallel.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import threading
|
||||
import queue
|
||||
import time
|
||||
|
||||
class Job():
|
||||
def __init__(self, func, args=[], kwargs={}, name=None):
|
||||
if name == None:
|
||||
name = 'job'
|
||||
self.id = None
|
||||
self.name = name
|
||||
self.func = func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.results = None
|
||||
|
||||
def run(self):
|
||||
self.results = self.func(*self.args, **self.kwargs)
|
||||
|
||||
def set_name(self, name):
|
||||
self.name = name
|
||||
|
||||
def set_id(self, jid):
|
||||
self.id = jid
|
||||
|
||||
def __call__(self):
|
||||
self.run()
|
||||
|
||||
class Worker(threading.Thread):
|
||||
def __init__(self, work_queue, finished_queue):
|
||||
super(Worker, self).__init__()
|
||||
self.queue = work_queue
|
||||
self.finished = finished_queue
|
||||
self.terminate = False
|
||||
self.daemon=True
|
||||
|
||||
def stop(self):
|
||||
self.terminate = True
|
||||
|
||||
def run(self):
|
||||
while not self.terminate:
|
||||
try:
|
||||
task = self.queue.get(timeout=1)
|
||||
task.run()
|
||||
self.queue.task_done()
|
||||
self.finished.put(task)
|
||||
except queue.Empty:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
print("you stop the threading")
|
||||
|
||||
class ParallelHost():
|
||||
def __init__(self, num_threads=8):
|
||||
self.num_threads = num_threads
|
||||
self.workers = []
|
||||
self.tasks = queue.Queue()
|
||||
self.results = queue.Queue()
|
||||
self.rets = {}
|
||||
self.id = 0
|
||||
for i in range(self.num_threads):
|
||||
worker = Worker(self.tasks, self.results)
|
||||
self.workers.append(worker)
|
||||
for worker in self.workers:
|
||||
worker.start()
|
||||
|
||||
def __del__(self):
|
||||
self.stop('kill')
|
||||
|
||||
# soft stop: wait until all job done
|
||||
# hard stop: stop even with unfinished job
|
||||
# kill stop: whatever the thread is doing, exit.
|
||||
def stop(self, mode='soft'):
|
||||
print('Trying to stop.')
|
||||
if mode == 'soft':
|
||||
self.tasks.join()
|
||||
print('All job finished.')
|
||||
for worker in self.workers:
|
||||
worker.stop()
|
||||
if mode == 'kill':
|
||||
worker.join(0.01)
|
||||
|
||||
def commit(self, job):
|
||||
self.id += 1
|
||||
job.set_id(self.id)
|
||||
self.tasks.put(job)
|
||||
return self.id
|
||||
|
||||
def add_job(self, func, args=[], kwargs={}, name=None):
|
||||
job = Job(func, args, kwargs, name)
|
||||
return self.commit(job)
|
||||
|
||||
def collect_all(self):
|
||||
while not self.results.empty():
|
||||
task = self.results.get()
|
||||
jid = task.id
|
||||
self.rets[jid] = task.results
|
||||
|
||||
def get_result(self, jid, block=False):
|
||||
if jid in self.rets:
|
||||
ret = self.rets[jid]
|
||||
del self.rets[jid]
|
||||
return ret
|
||||
while True:
|
||||
if self.results.empty() and not block:
|
||||
break
|
||||
task = self.results.get()
|
||||
if task.jid == jid:
|
||||
return task.results
|
||||
else:
|
||||
self.rets[task.jid] = task.results
|
||||
|
||||
def clear_results(self):
|
||||
while not self.results.empty():
|
||||
self.results.get()
|
||||
self.rets = {}
|
||||
|
||||
if __name__ == '__main__':
|
||||
host = ParallelHost()
|
||||
|
||||
def loop_print(info, num):
|
||||
for i in range(num):
|
||||
print(info + ':' + str(i))
|
||||
time.sleep(1)
|
||||
|
||||
for i in range(10):
|
||||
host.add_job(loop_print, ["loop_print_{0}".format(i), 5])
|
||||
|
||||
host.terminate('kill')
|
||||
151
lib/parser.py
Normal file
151
lib/parser.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from html.parser import HTMLParser
|
||||
from . import utils
|
||||
|
||||
def dict_to_arrtibute_string(attributes):
|
||||
string = ''
|
||||
for key in attributes:
|
||||
string += key + '=\"{0}\";'.format(str(attributes[key]))
|
||||
return string
|
||||
|
||||
def attribute_string_to_dict(attrs):
|
||||
attr_dict = {}
|
||||
for attr in attrs:
|
||||
attr_dict[attr[0]] = attr[1]
|
||||
return attr_dict
|
||||
|
||||
|
||||
class dom_node():
|
||||
def __init__(self, name = None, attributes = {}):
|
||||
if name is not None:
|
||||
self.name = name
|
||||
else:
|
||||
self.name = 'Node'
|
||||
|
||||
self.attributes = attributes
|
||||
self.childs = []
|
||||
self.data = None
|
||||
self.father = None
|
||||
|
||||
def add_child(self, child):
|
||||
if child is not None:
|
||||
child.father = self
|
||||
self.childs.append(child)
|
||||
|
||||
def to_string(self, prefix='', indent=' '):
|
||||
|
||||
string = prefix + '<' + self.name
|
||||
if self.attributes:
|
||||
string += ' ' + dict_to_arrtibute_string(self.attributes)
|
||||
string += '>\n'
|
||||
|
||||
for child in self.childs:
|
||||
string += child.to_string(prefix=prefix+indent, indent=indent)
|
||||
|
||||
if self.data is not None:
|
||||
string += prefix + indent + self.data + '\n'
|
||||
|
||||
string += prefix + '</{0}>\n'.format(self.name)
|
||||
|
||||
return string
|
||||
|
||||
|
||||
def has_child(self, name):
|
||||
has = False
|
||||
for child in self.childs:
|
||||
if child.name == name:
|
||||
has = True
|
||||
break;
|
||||
return has
|
||||
|
||||
def search(self, name):
|
||||
founded_node = []
|
||||
if type(name) is list:
|
||||
if self.name in name:
|
||||
founded_node.append(self)
|
||||
else:
|
||||
if self.name == name:
|
||||
founded_node.append(self)
|
||||
for child in self.childs:
|
||||
search_result = child.search(name)
|
||||
founded_node += search_result
|
||||
return founded_node
|
||||
|
||||
def dict2dom(d, root_name='root'):
|
||||
node = dom_node(root_name)
|
||||
for key in d:
|
||||
elem = d[key]
|
||||
child_node = dom_node(name=str(key))
|
||||
if type(elem) is dict:
|
||||
child_node = dict2dom(elem, root_name=str(key))
|
||||
elif type(elem) is list:
|
||||
for subelem in elem:
|
||||
if type(subelem) is dict:
|
||||
sub_node = dict2dom(subelem, root_name='li')
|
||||
child_node.add_child(sub_node)
|
||||
else:
|
||||
sub_node = dom_node('li')
|
||||
sub_node.data = str(subelem)
|
||||
child_node.add_child(sub_node)
|
||||
else:
|
||||
child_node.data = str(elem)
|
||||
node.add_child(child_node)
|
||||
return node
|
||||
|
||||
# if a dom node has data only, then it's {'name':'data'}
|
||||
# if a dom node has childs, then it's {'name':{}}
|
||||
# if a dom node has data as well as childs, data will be ignored.
|
||||
# if a dom has multi child with same name, it will be stored as list.
|
||||
def dom2dict(dom, replace_li = True):
|
||||
dictionary = {}
|
||||
for child in dom.childs:
|
||||
name = child.name
|
||||
content = None
|
||||
if len(child.childs) != 0:
|
||||
content = dom2dict(child, replace_li)
|
||||
else:
|
||||
content = child.data
|
||||
if content is None:
|
||||
content = ''
|
||||
content = utils.clean_text(content)
|
||||
if name in dictionary:
|
||||
if type(dictionary[name]) is not list:
|
||||
previous = dictionary[name]
|
||||
dictionary[name] = [previous, content]
|
||||
else:
|
||||
dictionary[name].append(content)
|
||||
else:
|
||||
dictionary[name] = content
|
||||
|
||||
if replace_li:
|
||||
for key in dictionary:
|
||||
item = dictionary[key]
|
||||
if type(item) is dict:
|
||||
li = None
|
||||
if len(item.keys()) == 1:
|
||||
for subkey in item:
|
||||
if subkey == 'li':
|
||||
li = item[subkey]
|
||||
if li is not None:
|
||||
dictionary[key] = li
|
||||
return dictionary
|
||||
|
||||
class simple_parser(HTMLParser):
|
||||
def __init__(self):
|
||||
super(simple_parser, self).__init__()
|
||||
self.root = dom_node('root')
|
||||
self.current_node = self.root
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
attrs_dict = attribute_string_to_dict(attrs)
|
||||
this_node = dom_node(tag, attrs_dict)
|
||||
self.current_node.add_child(this_node)
|
||||
self.current_node = this_node
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
self.current_node = self.current_node.father
|
||||
|
||||
def handle_data(self, data):
|
||||
if self.current_node.data is None:
|
||||
self.current_node.data = data
|
||||
else:
|
||||
self.current_node.data += data
|
||||
19
lib/screen.py
Normal file
19
lib/screen.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import sys
|
||||
|
||||
class VirtualScreen():
|
||||
def __init__(self, max_history=1000):
|
||||
self.max_history = max_history
|
||||
self.contents = []
|
||||
|
||||
def write(self, message):
|
||||
self.contents.append(message)
|
||||
|
||||
def last(self, line=10, output=sys.stdout):
|
||||
num_lines = len(self.contents)
|
||||
start_line = num_lines - line
|
||||
if start_line < 0:
|
||||
start_line = 0
|
||||
display = self.contents[start_line:]
|
||||
for line in display:
|
||||
output.write(line)
|
||||
output.write('\n')
|
||||
244
lib/service.py
Normal file
244
lib/service.py
Normal file
@@ -0,0 +1,244 @@
|
||||
import time
|
||||
import sys
|
||||
import shlex
|
||||
import argparse
|
||||
|
||||
from croniter import croniter
|
||||
from . import utils
|
||||
from . import parallel
|
||||
from . import console
|
||||
from . import screen
|
||||
from . import utils
|
||||
|
||||
class service():
|
||||
def __init__(self, action, args=[], kwargs={}, cron='* * * * *', managed_output=False, name='service'):
|
||||
self.name = name
|
||||
self.action = action
|
||||
self.managed_output = managed_output
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.output = sys.stdout
|
||||
self.last_result = None
|
||||
self.cronexpr = cron
|
||||
self.croniter = croniter(self.cronexpr, time.time())
|
||||
self.next_time = self.croniter.get_next()
|
||||
|
||||
def run(self, daemon=None, dry=False):
|
||||
if not dry:
|
||||
self.next_time = self.croniter.get_next()
|
||||
|
||||
new_args = []
|
||||
if self.managed_output:
|
||||
new_args = [self.output, *self.args]
|
||||
else:
|
||||
new_args = self.args
|
||||
if daemon is None:
|
||||
self.last_result = self.action(*new_args, **self.kwargs)
|
||||
else:
|
||||
daemon.add_job(self.action, new_args, self.kwargs, self.name)
|
||||
|
||||
class ServiceManager():
|
||||
def __init__(self, debug=False, output=sys.stdout):
|
||||
self.debug = debug
|
||||
self.services = {}
|
||||
self.deleted_services = {}
|
||||
self.protected_service = []
|
||||
self.daemon = parallel.ParallelHost()
|
||||
self.sid = 0
|
||||
self.terminate = False
|
||||
self.output = output
|
||||
|
||||
self.set_refresh_time()
|
||||
|
||||
def stop(self):
|
||||
self.daemon.stop()
|
||||
self.terminate = True
|
||||
|
||||
def __del__(self):
|
||||
self.stop()
|
||||
|
||||
def log(self, *args, end='\n'):
|
||||
self.output.write('[{0}]'.format(utils.str_time()))
|
||||
for arg in args:
|
||||
arg = str(arg)
|
||||
self.output.write(arg)
|
||||
self.output.write(end)
|
||||
|
||||
def add(self, service, protected=False):
|
||||
self.sid += 1
|
||||
service.output = self.output
|
||||
self.services[self.sid] = service
|
||||
if protected:
|
||||
self.protected_service.append(self.sid)
|
||||
return self.sid
|
||||
|
||||
def delete(self, sid):
|
||||
if sid in self.protected_service:
|
||||
self.log('Can not delete protected service.')
|
||||
return
|
||||
if sid in self.services:
|
||||
self.deleted_services[sid] = self.services[sid]
|
||||
del self.services[sid]
|
||||
else:
|
||||
self.log('The sid [{0}] do not exist!'.format(sid))
|
||||
|
||||
def recover(self, sid):
|
||||
if sid in self.deleted_services:
|
||||
self.services[sid] = self.deleted_services[sid]
|
||||
del self.deleted_services[sid]
|
||||
else:
|
||||
self.log('The sid [{0}] is not found recycle bin.'.format(sid))
|
||||
|
||||
def set_refresh_time(self, refresh_cron='* * * * *'):
|
||||
def refresh():
|
||||
pass
|
||||
refresh_service = service(refresh, cron=refresh_cron, name='refresh')
|
||||
self.add(refresh_service, protected = True)
|
||||
|
||||
def get_next(self):
|
||||
next_sid = -1
|
||||
next_time = -1
|
||||
for sid in self.services:
|
||||
service = self.services[sid]
|
||||
if service.next_time < next_time or next_sid < 0:
|
||||
next_sid = sid
|
||||
next_time = service.next_time
|
||||
return next_sid, next_time
|
||||
|
||||
def loop(self):
|
||||
while not self.terminate:
|
||||
next_sid, next_time = self.get_next()
|
||||
service = self.services[next_sid]
|
||||
sleep_time = next_time - time.time()
|
||||
if sleep_time > 0:
|
||||
time.sleep(sleep_time)
|
||||
self.log('Running service {0} (SID={1})'.format(service.name, next_sid))
|
||||
if next_sid in self.services:
|
||||
service.run(self.daemon)
|
||||
else:
|
||||
self.log('the sheduled service wiil not run since it is canceled.')
|
||||
|
||||
|
||||
# mode: background: return immidietly
|
||||
# foreground: stuck here.
|
||||
def start(self, mode='background'):
|
||||
if mode == 'background':
|
||||
self.daemon.add_job(self.loop, name='service main loop')
|
||||
else:
|
||||
self.loop()
|
||||
|
||||
def get_service_console(manager, name='service'):
|
||||
|
||||
con = console.console(name)
|
||||
|
||||
def command_show(args):
|
||||
print('Active services:')
|
||||
for sid in manager.services:
|
||||
print('SID: {0} | Name: {1}'.format(sid, manager.services[sid].name))
|
||||
print('Deleted services:')
|
||||
for sid in manager.deleted_services:
|
||||
print('SID: {0} | Name: {1}'.format(sid, manager.deleted_services[sid].name))
|
||||
|
||||
def command_add(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('cron', type=str, help='A cron expr')
|
||||
parser.add_argument('task', type=str, help='task to run, should be a valid command')
|
||||
parser.add_argument('--name', '-n', type=str, default='command service', help='name of the task')
|
||||
args = shlex.split(args)
|
||||
args = parser.parse_args(args)
|
||||
cron = args.cron
|
||||
if not croniter.is_valid(cron):
|
||||
print('Invalid cron expression.')
|
||||
task = args.task
|
||||
name = args.name
|
||||
service_to_add = service(con.execute, args=[task], cron=cron, name=name)
|
||||
manager.add(service_to_add)
|
||||
|
||||
def command_delete(args):
|
||||
sid = None
|
||||
if args.isdigit():
|
||||
if int(args) in manager.services:
|
||||
sid = int(args)
|
||||
if sid is not None:
|
||||
manager.delete(sid)
|
||||
else:
|
||||
print('command arugment \"{0}\" is not understood.'.format(args))
|
||||
|
||||
def command_recover(args):
|
||||
sid = None
|
||||
if args.isdigit():
|
||||
if int(args) in manager.deleted_services:
|
||||
sid = int(args)
|
||||
if sid is not None:
|
||||
manager.recover(sid)
|
||||
else:
|
||||
print('command arugment \"{0}\" is not understood.'.format(args))
|
||||
|
||||
def command_run(args):
|
||||
sid = None
|
||||
if args.isdigit():
|
||||
if int(args) in manager.services:
|
||||
sid = int(args)
|
||||
if sid is not None:
|
||||
manager.services[sid].run(dry=True)
|
||||
else:
|
||||
print('command arugment \"{0}\" is not understood.'.format(args))
|
||||
|
||||
def command_info(args):
|
||||
line = None
|
||||
if args != '':
|
||||
if args.isdigit():
|
||||
line = int(args)
|
||||
if line is None:
|
||||
line = 10
|
||||
manager.output.last(line)
|
||||
|
||||
def command_next(args):
|
||||
next_sid, next_time = manager.get_next()
|
||||
info = ''
|
||||
indent = ' '
|
||||
info += 'Next Job: {0}'.format(manager.services[next_sid].name)
|
||||
info += '\n{0}SID: {1}'.format(indent, next_sid)
|
||||
info += '\n{0}Scheduled Running Time: {1}'.format(indent, utils.time2str(next_time))
|
||||
info += '\n{0}Remeaning Time: {1}s'.format(indent, utils.float2str(next_time-time.time()))
|
||||
print(info)
|
||||
|
||||
con.regist('show', command_show, help_info='Show all services.', alias=['ls'])
|
||||
con.regist('run', command_run, help_info='Run a service.')
|
||||
con.regist('info', command_info, help_info='Display service output log.')
|
||||
con.regist('next', command_next, help_info='Next job to run.')
|
||||
con.regist('add', command_add, help_info='Register a command as service.')
|
||||
con.regist('delete', command_delete, help_info='Delete a service', alias=['del'])
|
||||
con.regist('recover', command_recover, help_info='Recover a service.')
|
||||
return con
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def func1(output):
|
||||
output.write('func1')
|
||||
|
||||
def func2(output):
|
||||
output.write('func2')
|
||||
|
||||
def add(a, b):
|
||||
print('{0} + {1} = {2}'.format(a, b, a+b))
|
||||
|
||||
def command_add(args):
|
||||
numbers = args.split(' ')
|
||||
a = float(numbers[0])
|
||||
b = float(numbers[1])
|
||||
add(a, b)
|
||||
|
||||
log_screen = screen.VirtualScreen()
|
||||
manager = ServiceManager(output=log_screen)
|
||||
test1 = service(func1, cron='* * * * *', name='test1', managed_output=True)
|
||||
test2 = service(func2, cron='* * * * *', name='test2', managed_output=True)
|
||||
manager.add(test1)
|
||||
manager.add(test2)
|
||||
manager.start('background')
|
||||
|
||||
con = get_service_console(manager)
|
||||
master = console.console()
|
||||
master.regist('service', con, help_info='service console')
|
||||
master.regist('add', command_add, help_info='Add two numbers.')
|
||||
master.interactive()
|
||||
15
lib/try.py
Normal file
15
lib/try.py
Normal file
@@ -0,0 +1,15 @@
|
||||
def func(a, b, c, time=0, work=1):
|
||||
print('a:{0} b:{1} c:{2}'.format(a, b, c))
|
||||
print('time:{0} work:{1}'.format(time, work))
|
||||
|
||||
def funcwrap(func, kargs, kkargs):
|
||||
func(*kargs, **kkargs)
|
||||
|
||||
|
||||
kargs = [1, 2, 3]
|
||||
kkargs = {
|
||||
"time":1234,
|
||||
"work":1232
|
||||
}
|
||||
|
||||
funcwrap(func, kargs, kkargs)
|
||||
139
lib/utils.py
Normal file
139
lib/utils.py
Normal file
@@ -0,0 +1,139 @@
|
||||
import pickle
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
import platform
|
||||
|
||||
def detect_platform():
|
||||
p = 'Unknown'
|
||||
if platform.platform().find('Windows') != -1:
|
||||
p = 'Windows'
|
||||
elif platform.platform().find('Linux') != -1:
|
||||
p = 'Linux'
|
||||
return p
|
||||
|
||||
def ensure_dir_exist(directory, show_info = True):
|
||||
exist = os.path.isdir(directory)
|
||||
if not exist:
|
||||
print('directory', directory, ' not found, creating...')
|
||||
os.mkdir(directory)
|
||||
|
||||
def validateTitle(title):
|
||||
rstr = r"[\/\\\:\*\?\"\<\>\|]" # '/ \ : * ? " < > |'
|
||||
new_title = re.sub(rstr, " ", title) # 替换为空格
|
||||
return new_title
|
||||
|
||||
def list2csv(l):
|
||||
csv = ''
|
||||
for item in l:
|
||||
csv += str(item) + ','
|
||||
csv = csv[:-1]
|
||||
return csv
|
||||
|
||||
def clean_text(string):
|
||||
if string is None:
|
||||
return ''
|
||||
while '\n' in string:
|
||||
string = string.replace('\n', ' ')
|
||||
splits = clean_split(string)
|
||||
string = ''
|
||||
for split in splits:
|
||||
string += split + ' '
|
||||
string = string[:-1]
|
||||
return string
|
||||
|
||||
def clean_split(string, delimiter=' '):
|
||||
sub_strs = string.split(delimiter)
|
||||
splits = []
|
||||
for sub_str in sub_strs:
|
||||
if sub_str is not '':
|
||||
splits.append(sub_str)
|
||||
return splits
|
||||
|
||||
def remove_blank_in_endpoint(string):
|
||||
length = len(string)
|
||||
|
||||
first_index = 0
|
||||
for i in range(length):
|
||||
if is_blank(string[first_index]):
|
||||
first_index += 1
|
||||
else:
|
||||
break
|
||||
|
||||
last_index = length - 1
|
||||
for i in range(length):
|
||||
if is_blank(string[last_index]):
|
||||
last_index -= 1
|
||||
else:
|
||||
break
|
||||
last_index += 1
|
||||
return string[first_index:last_index]
|
||||
|
||||
def is_blank(ch):
|
||||
blank_ch = [' ', '\t', '\n']
|
||||
if ch in blank_ch:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def dict_to_arrtibute_string(attributes):
|
||||
string = ''
|
||||
for key in attributes:
|
||||
string += key + '=\"{0}\";'.format(str(attributes[key]))
|
||||
return string
|
||||
|
||||
def attribute_string_to_dict(attrs):
|
||||
attr_dict = {}
|
||||
for attr in attrs:
|
||||
attr_dict[attr[0]] = attr[1]
|
||||
return attr_dict
|
||||
|
||||
def save_python_object(obj, save_path):
|
||||
with open(save_path, 'wb') as file:
|
||||
pickle.dump(obj, file)
|
||||
|
||||
def load_python_object(path):
|
||||
with open(path, 'rb') as file:
|
||||
return pickle.load(file)
|
||||
|
||||
def delete_n(string):
|
||||
while '\n' in string:
|
||||
string = string.replace('\n', ' ')
|
||||
return string
|
||||
|
||||
def remove_additional_blank(string):
|
||||
words = string.split(' ')
|
||||
string = ''
|
||||
for word in words:
|
||||
if word is not '':
|
||||
string += word + ' '
|
||||
return string[:-1]
|
||||
|
||||
def formal_text(text):
|
||||
text = delete_n(text)
|
||||
text = remove_additional_blank(text)
|
||||
return text
|
||||
|
||||
def float2str(f, precision=2):
|
||||
f = str(f)
|
||||
f_base = f[:f.find('.') + precision]
|
||||
return f_base
|
||||
|
||||
# ========== time realted operation ========== #
|
||||
|
||||
def str_day():
|
||||
day = time.strftime("%Y-%m-%d", time.localtime())
|
||||
return day
|
||||
|
||||
def time2str(t):
|
||||
localtime = time.localtime(int(t))
|
||||
return str_time(localtime)
|
||||
|
||||
def str_time(local_time = None):
|
||||
if local_time is None:
|
||||
local_time = time.localtime()
|
||||
day = time.strftime("%Y-%m-%d-%Hh-%Mm-%Ss)", local_time)
|
||||
return day
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(str_day())
|
||||
Reference in New Issue
Block a user