Merge branch 'master' of decade.cz:overwatch/over

This commit is contained in:
Martin 2019-05-29 13:50:43 +02:00
commit 88be91445f
4 changed files with 78 additions and 24 deletions

View file

@ -53,27 +53,56 @@ def strings(*args):
return out
def directory(exists=False, writable=False, gio=False):
def path(exists=False, permissions=None, validators=None):
"""
Returns a directory callback that raises hell if:
- the supplied directory doesn't exist and `exists` is True
- isn't writable and `writable` is True
- isn't a valid Gio path and `gio` is True
Returns a path callback that takes a path (str) and verifies if it:
- exists iff `exists` is True
- its permissions match those in `permissions` ("rwx" or any subset, e.g. "r--", "-w-", dashes are optional)
- goes through each (function, message) pair in `validators`, in order
@while generating a callback
A validator is a function that takes a str argument and returns True or False.
If False is returned, the matching message is raised along with a RuntimeError.
The message may contain %s to be replaced by the supplied path. Example:
validators=[
(os.path.isdir, "%s is not a directory"),
(os.path.isabs, "%s is a directory, but is not an absolute path.")
]
@while generating a path callback
"""
if gio:
raise NotImplementedError("Gio support is not yet here")
def cb(arg):
path = os.path.abspath(os.path.expanduser(arg))
if not os.path.isdir(path) and exists:
raise FileNotFoundError("%s (%s) does not exist" %(arg, path))
if exists and not os.path.exists(path):
raise FileNotFoundError("%s does not exist" %(arg))
if writable and not os.access(path, os.W_OK | os.X_OK):
raise PermissionError("%s exists but is not writable" %(arg))
if permissions:
if "r" in permissions and not os.access(path, os.R_OK):
raise PermissionError("%s is not readable" %(arg))
if "w" in permissions and not os.access(path, os.W_OK):
raise PermissionError("%s is not writable" %(arg))
if "x" in permissions and not os.access(path, os.X_OK):
raise PermissionError("%s is not executable" %(arg))
if validators:
if hasattr(validators, "__iter__"):
src = validators
else:
src = [validators]
for v in src:
if hasattr(v, "__iter__"):
fn, msg_tpl = v
else:
fn = v
msg_tpl = "%%s failed validation by '%s'" %(fn.__name__)
if not fn(path):
msg = msg_tpl %(arg) if "%s" in msg_tpl else msg_tpl
raise RuntimeError(msg)
return path

View file

@ -61,6 +61,9 @@ class Command:
self.__dict__["sequence_original"] = list(sequence)
self.reset()
def __str__(self):
return " ".join(self.dump(pretty=True))
def __setattr__(self, name, value):
found = False

View file

@ -110,7 +110,7 @@ def debugger():
# --------------------------------------------------
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):
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, skip_same=True):
"""
Writes a hex dump of `data` to `output`.
@ -120,6 +120,7 @@ def hexdump(data, indent=0, width=16, show_header=True, show_offsets=True, show_
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.
If `skip_same` is True, lines with identical content are abbreviated (omitted).
@while creating a hex dump
"""
@ -153,13 +154,10 @@ def hexdump(data, indent=0, width=16, show_header=True, show_offsets=True, show_
output_io.write(" ".join(line) + "\n")
skip_cnt = 0
last_hex_bytes = None
while data[ptr:]:
if indent:
output_io.write(" " * indent)
if show_offsets:
output_io.write(format_str %(initial_offset + ptr))
hex_bytes = []
ascii_bytes = []
@ -175,6 +173,29 @@ def hexdump(data, indent=0, width=16, show_header=True, show_offsets=True, show_
elif i == len(data):
hex_bytes.extend([" "] * (width - local_i))
ptr += width
# the rest is just rendering
if skip_same:
if hex_bytes == last_hex_bytes:
skip_cnt += 1
else:
if skip_cnt:
output_io.write("(skipped %d lines, %d B)\n" %(skip_cnt, skip_cnt * width))
skip_cnt = 0
last_hex_bytes = hex_bytes
if skip_cnt:
continue
if indent:
output_io.write(" " * indent)
if show_offsets:
output_io.write(format_str %(initial_offset + ptr))
if use_colors: output_io.write(text.render("<W>"))
output_io.write(" ".join(hex_bytes))
if use_colors: output_io.write(text.render("<.>"))
@ -185,8 +206,9 @@ def hexdump(data, indent=0, width=16, show_header=True, show_offsets=True, show_
output_io.write(text.render("<.>|") if use_colors else "|")
output_io.write("\n")
ptr += width
if skip_cnt:
output_io.write("(skipped %d lines, %d B)\n" %(skip_cnt, skip_cnt * width))
if not output:
output_io.seek(0)

View file

@ -4,5 +4,5 @@
major = 2 # VERSION_MAJOR_IDENTIFIER
minor = 1 # VERSION_MINOR_IDENTIFIER
# VERSION_LAST_MM 2.1
patch = 0 # VERSION_PATCH_IDENTIFIER
str = "2.1.0" # VERSION_STRING_IDENTIFIER
patch = 5 # VERSION_PATCH_IDENTIFIER
str = "2.1.5" # VERSION_STRING_IDENTIFIER