over/over/misc.py
2017-10-16 10:49:24 +02:00

221 lines
5 KiB
Python

#! /usr/bin/env python3
# encoding: utf-8
import sys
# --------------------------------------------------
def import_module(path):
"""
Imports a python file as a module. The `path` can be relative or absolute.
Based on the work of Yuval Greenfield released into the public domain.
@while importing a module
"""
import imp
import os
path = os.path.expanduser(path)
# remove the .py suffix
mod_dirname = os.path.dirname(path)
mod_filename = os.path.basename(path)
if mod_filename.endswith(".py"):
mod_name = mod_filename[:-3]
else:
# packages for example
mod_name = mod_filename
fd = None
try:
data = imp.find_module(mod_name, [mod_dirname])
module = imp.load_module(mod_name, *data)
fd = data[0]
finally:
if fd is not None:
fd.close()
return module
# --------------------------------------------------
def batch_gen(data, batch_size):
"""
Split `data` (a sequence) into sequences `batch_size` elements long.
"""
for i in range(0, len(data), batch_size):
yield data[i:i+batch_size]
# --------------------------------------------------
def update_dict(A, B, overwrite=False):
"""
Shallow-copies items from B to A.
Iff `overwrite`, keys that already exist in A will be overwritten.
Otherwise, only keys that aren't in A will be set.
"""
for key, value in B.items():
if key not in A:
A[key] = value
# --------------------------------------------------
def console(override_environment=None, tab_completion=True):
"""
Opens up a Python console.
If no `override_environment` is passed, the environment of the calling stack frame (and all parent stack frames) will be used.
"""
import code
import copy
import inspect
import readline
import rlcompleter
if override_environment:
environment = override_environment
else:
environment = {}
frame = inspect.currentframe()
while frame:
update_dict(environment, frame.f_locals)
frame = frame.f_back
if tab_completion:
readline.parse_and_bind("tab: complete")
c = code.InteractiveConsole(environment)
c.interact(banner="")
# --------------------------------------------------
def debugger():
"""
Drops into the Python Debugger where called.
"""
import pdb
pdb.set_trace()
# --------------------------------------------------
def hexdump(data, indent=0, width=16, show_header=True, show_offsets=True, show_ascii=True, use_colors=True, initial_offset=0, output=sys.stdout):
"""
Writes a hex dump of `data` to `output`.
The output text is indented with spaces and contains `width` bytes per line.
If `show_header` is True, a single line with byte numbers preceeds all output.
If `show_offsets` is True, each line is prefixed with the address of the first byte of that line.
If `show_ascii` is True, each line is suffixed with its ASCII representation. Unprintable characters
are replaced with a dot.
The `output` must implement a .write(str x) method. If `output` is None, the string is returned instead.
@while creating a hex dump
"""
import io
import math
from . import text
output_io = io.StringIO() if not output else output
try:
data = bytes(data)
except:
raise ValueError("data must be bytes or similar")
offset_figures = math.ceil(math.log2(len(data)) / 8) * 2 if data else 2
format_str = "%%0%dx " %(offset_figures)
ptr = 0
if show_header:
line = []
if show_offsets:
line.append("offset"[:offset_figures].ljust(offset_figures + 2))
for i in range(width):
line.append("%2x" %(i))
if show_ascii:
line.append(" *{0}*".format("ASCII".center(width, "-")))
output_io.write(" ".join(line) + "\n")
while data[ptr:]:
if indent:
output_io.write(" " * indent)
if show_offsets:
output_io.write(format_str %(initial_offset + ptr))
hex_bytes = []
ascii_bytes = []
for local_i, i in enumerate(range(ptr, ptr+width)):
if i < len(data):
c = data[i]
hex_bytes.append("%02x" %(c))
if 0x20 <= c <= 0x7e:
ascii_bytes.append(chr(c))
else:
ascii_bytes.append(".")
elif i == len(data):
hex_bytes.extend([" "] * (width - local_i))
if use_colors: output_io.write(text.render("<W>"))
output_io.write(" ".join(hex_bytes))
if use_colors: output_io.write(text.render("<.>"))
if show_ascii:
output_io.write(text.render(" | <W>") if use_colors else " |")
output_io.write("".join(ascii_bytes))
output_io.write(text.render("<.>|") if use_colors else "|")
output_io.write("\n")
ptr += width
if not output:
output_io.seek(0)
return output_io.read()
# --------------------------------------------------
def raw_to_hex(raw, spaces=True):
"""
Converts a bytearray (or bytes) into its textual hexadecimal representation.
"""
output = []
for o in raw:
output.append(hex(o)[2:].zfill(2))
return (" " if spaces else "").join(output)
def hex_to_raw(text):
"""
Converts a hexadecimal representation of a byte array into a bytearray.
"""
output = []
text = text.replace(" ", "")
for i in range(len(text)//2):
output.append(int(text[2*i:2*i+2], 16))
return bytearray(output)