340 lines
8.5 KiB
Cython
340 lines
8.5 KiB
Cython
# class Autoloader:
|
|
# """
|
|
# Python module autoloader. To activate, call et.autoloader.register() from python shell.
|
|
# Try not to rely on it as it'll betray you when there's more than one new module in a single command.
|
|
# """
|
|
|
|
# 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 = textfilter(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
|
|
# output("Autoloaded module §g%s§/" %(module_name), 0, timestamp=True)
|
|
# 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)
|
|
|
|
# def wait(seconds_target, text="", minutes=True, progress_bar=True, countdown=False):
|
|
# """
|
|
# int seconds how long to wait
|
|
# str text display this text before the timer
|
|
# bool minutes use mm:ss ?
|
|
# bool progress_bar display a progress bar ? TODO
|
|
# bool countdown count down instead of up
|
|
|
|
# Wait clock. Don't use it on larger scales, i.e. hours, as it accumulates little error every tick
|
|
# and you may end up waiting extra minutes or even dead.
|
|
|
|
# Returns True if zero is reached, False if interrupted.
|
|
# """
|
|
|
|
# seconds = 0
|
|
|
|
# try:
|
|
# while seconds <= seconds_target:
|
|
# if countdown:
|
|
# seconds_use = seconds_target - seconds
|
|
# else:
|
|
# seconds_use = seconds
|
|
|
|
# if minutes:
|
|
# mins = str(seconds_use/60).zfill(2)
|
|
# secs = str(seconds_use%60).zfill(2)
|
|
|
|
# mins_target = str(seconds_target/60).zfill(2)
|
|
# secs_target = str(seconds_target%60).zfill(2)
|
|
|
|
# time_tag = "%s:%s / %s:%s" %(mins, secs, mins_target, secs_target)
|
|
# else:
|
|
# time_tag = "%s / %s" %(seconds_use, seconds_target)
|
|
|
|
# prog_bar = " "
|
|
# if progress_bar:
|
|
# # determine how much space we have to crap up... I mean use
|
|
# # 13 = 8 spaces at the end, 5 for ' [>] '
|
|
# width_max = get_terminal_size()[1] - len(re.sub("§.", "", text)) - len(time_tag) - 20
|
|
# left_side = int((seconds/float(seconds_target)) * width_max)
|
|
# right_side = width_max - left_side
|
|
|
|
# prog_bar = " [%s>%s] " %('='*left_side, ' '*right_side)
|
|
|
|
# output(text+prog_bar+time_tag+' \r', 0, newline=False)
|
|
|
|
# if not seconds == seconds_target:
|
|
# time.sleep(1)
|
|
|
|
# seconds += 1
|
|
|
|
# except (EOFError, KeyboardInterrupt):
|
|
# output(text+prog_bar+time_tag+' ', 3)
|
|
# return False
|
|
|
|
# else:
|
|
# output(text+prog_bar+time_tag+' ', 2)
|
|
# return True
|
|
|
|
# def progress(part, width=None, before="", after="", show_percent=True, newline=False):
|
|
# """
|
|
# Display a progress bar.
|
|
|
|
# float part 0.0 to 1.0
|
|
# int width width in cols, defaults to terminal width
|
|
# str before text displayed before the progress bar
|
|
# str after text displayed after the progress bar
|
|
# bool show_percent display percent after the bar (but before the after part)
|
|
# bool newline append a \n
|
|
# """
|
|
|
|
# if not width:
|
|
# width = get_terminal_size()[1]
|
|
|
|
# width_bar = width - 2 - 2 - 1
|
|
# # a b c
|
|
# # a = space on each side of the terminal
|
|
# # b = [ and ]
|
|
# # c = >
|
|
|
|
|
|
# if before:
|
|
# width_bar -= 1 + len(before)
|
|
# before = before + " "
|
|
|
|
# if after:
|
|
# width_bar -= 1 + len(after)
|
|
# after = " " + after
|
|
|
|
# if show_percent:
|
|
# width_bar -= 5
|
|
# percent = "%s%% " %(str(int(round(part*100))).rjust(3))
|
|
|
|
# if not newline:
|
|
# r_part = "\r"
|
|
# else:
|
|
# r_part = ""
|
|
|
|
# output(" %s%s[%s>%s]%s %s" %(before, percent, "="*int(part*width_bar), " "*(int((1-part)*width_bar)), after, r_part), newline=newline)
|
|
|
|
# class Unit:
|
|
# _prefixes = ( ("Y", 24), ("Z", 21), ("E", 18), ("P", 15), ("T", 12), ("G", 9), ("M", 6), ("k", 3), ("", 0),
|
|
# ("m", -3), ("μ", -6), ("n", -9), ("p", -12), ("f", -15), ("a", -18), ("z", -21), ("y", -24))
|
|
# #("c", -2),
|
|
|
|
# def __init__(self, initializer, force_unit=None, dimension=1, space=True):
|
|
# self.space = space
|
|
# self.dimension = dimension
|
|
|
|
# if type(initializer) == str: # init from text
|
|
# integer, decimal, unit = re.findall("(\d+)[.,]*(\d*)\s*(\D+)", initializer)[0]
|
|
# self.value = float("%s.%s" %(integer, decimal))
|
|
|
|
# if len(unit) >= 2:
|
|
# prefix = self._prefix_to_multiplier(unit[0])
|
|
|
|
# if prefix != None:
|
|
# self.value *= 10**(prefix*self.dimension)
|
|
# self.unit = unit[1:]
|
|
# else:
|
|
# self.unit = unit
|
|
# else:
|
|
# self.unit = unit
|
|
|
|
# if force_unit:
|
|
# self.unit = force_unit
|
|
|
|
# else: # init from float, str unit and int dimension
|
|
# self.value = float(initializer)
|
|
# self.unit = force_unit
|
|
|
|
# def _prefix_to_multiplier(self, prefix):
|
|
# for p, mul in self._prefixes:
|
|
# if p == prefix:
|
|
# return mul
|
|
|
|
# return None
|
|
|
|
# def __repr__(self):
|
|
# value = self.value
|
|
|
|
# if value < 0:
|
|
# sign = -1
|
|
# value *= -1
|
|
# else:
|
|
# sign = 1
|
|
|
|
# if value == 0.0:
|
|
# e = 0
|
|
# else:
|
|
# e = round(math.log(value, 10), 6)
|
|
|
|
# for prefix, mul in self._prefixes:
|
|
# if mul*self.dimension <= e:
|
|
# break
|
|
|
|
# if self.unit:
|
|
# unit = self.unit
|
|
# else:
|
|
# unit = ""
|
|
|
|
# if self.space:
|
|
# space = " "
|
|
# else:
|
|
# space = ""
|
|
|
|
# return "%.2f%s%s%s" %(sign*value/10**(mul*self.dimension), space, prefix, unit)
|
|
|
|
# by ephemient@stackoverflow.com
|
|
def touch(fname, times=None):
|
|
with open(fname, 'a'):
|
|
os.utime(fname, times)
|
|
|
|
def console(environment):
|
|
"""
|
|
Opens up a Python console.
|
|
|
|
Typical usage: over.console(locals())
|
|
"""
|
|
|
|
import code, readline, rlcompleter
|
|
|
|
readline.parse_and_bind("tab: complete")
|
|
|
|
_print = Output("over.core", default_suffix=".\n", timestamp=True, tb=False)
|
|
_print("opening Python console", prefix.start)
|
|
|
|
c = code.InteractiveConsole(environment)
|
|
c.interact(banner="")
|
|
|
|
class enum:
|
|
"""
|
|
Emulates a C++-like enum type.
|
|
|
|
Based on a py2 enum function by Alec Thomas and acjohnson55.
|
|
"""
|
|
|
|
def __init__(self, name, words, start=0):
|
|
self.typename = name
|
|
self.reverse_enums = dict(enumerate(words, start))
|
|
self.enums = dict((value, key) for key, value in self.reverse_enums.items())
|
|
|
|
def name(self, value):
|
|
if value in self.reverse_enums:
|
|
return self.reverse_enums[value]
|
|
else:
|
|
raise AttributeError("No attribute of %s has a value of %s." %(self, value))
|
|
|
|
def __getattr__(self, aname):
|
|
if aname in self.enums:
|
|
return self.enums[aname]
|
|
else:
|
|
raise AttributeError("%s not in %s." %(aname, self))
|
|
|
|
def __repr__(self):
|
|
return "<enum %s>" %(self.typename)
|
|
|
|
class map:
|
|
def __init__(self, source=None):
|
|
"""
|
|
source is a zipped list: [(key, value), (key, value), ...]
|
|
"""
|
|
|
|
if source:
|
|
self.keys, self.vals = zip(*source)
|
|
else:
|
|
self.keys = []
|
|
self.vals = []
|
|
|
|
def __get_index(self, key):
|
|
if key in self.keys:
|
|
return self.keys.index(key)
|
|
else:
|
|
return None
|
|
|
|
def __getitem__(self, key):
|
|
i = self.__get_index(key)
|
|
|
|
if i is None:
|
|
raise KeyError(key)
|
|
else:
|
|
return self.vals[i]
|
|
|
|
def __setitem__(self, key, val):
|
|
i = self.__get_index(key)
|
|
|
|
if i is None:
|
|
self.keys.append(key)
|
|
self.vals.append(val)
|
|
else:
|
|
self.vals[i] = val
|
|
|
|
def __contains__(self, item):
|
|
return item in self.keys
|
|
|
|
def index(self, item):
|
|
return self.keys.index(item)
|
|
|
|
def sort(self, key=None):
|
|
tmp_keys = self.keys
|
|
tmp_vals = self.vals
|
|
|
|
self.keys = []
|
|
self.vals = []
|
|
|
|
for K, V in sorted(zip(tmp_keys, tmp_vals), key=key):
|
|
self.keys.append(K)
|
|
self.vals.append(V)
|
|
|
|
@property
|
|
def items(self):
|
|
return zip(self.keys, self.vals)
|
|
|
|
def __len__(self):
|
|
return len(self.vals)
|
|
|
|
def __repr__(self):
|
|
pairs = []
|
|
|
|
for i in range(len(self.keys)):
|
|
pairs.append("%s: %s" %(repr(self.keys[i]), repr(self.vals[i])))
|
|
|
|
return "<{%s}>" %(", ".join(pairs))
|
|
|
|
def batch_gen(data, batch_size):
|
|
"""
|
|
by rpr (stackoverflow)
|
|
"""
|
|
|
|
for i in range(0, len(data), batch_size):
|
|
yield data[i:i+batch_size]
|
|
|
|
class ndict(dict):
|
|
def __init__(self, *args, **kwargs):
|
|
dict.__init__(self, *args, **kwargs)
|
|
|
|
def __getattr__(self, name):
|
|
if name in self:
|
|
return self[name]
|
|
else:
|
|
raise AttributeError("'ndict' object has no attribute '%s'" %(name))
|
|
|
|
def __setattr__(self, name, value):
|
|
self[name] = value
|