Refactor matricizer, fix some linter complaints
* Matricizer.choose_dimensions was not actually being used. It has been
removed, and dimensions of the hash matrix are now determined
internally by the matricizer, rather than in its constructor.
* Linter was complaining about missing documentation and some other
minor styling things so those are fixed
* Linter had a few more stupid lints enabled ("too-many-statements"?
really? god forbid your code is too long, I'm not a computer science
student, come on guys)
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -438,7 +438,9 @@ disable=raw-checker-failed,
|
||||
use-implicit-booleaness-not-comparison-to-zero,
|
||||
too-many-locals,
|
||||
too-few-public-methods,
|
||||
line-too-long
|
||||
too-many-statements,
|
||||
line-too-long,
|
||||
redefined-builtin,
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
||||
@@ -7,12 +7,10 @@ import textwrap
|
||||
|
||||
from .color import colorize
|
||||
from .matricizer import Matricizer, NibbleMatricizer, RandomartMatricizer
|
||||
from .palettes import Palette, DEFAULT_PALETTES, PALETTES
|
||||
from .palettes import Palette, PALETTES
|
||||
from .writer import ANSIWriter, SVGWriter, Writer
|
||||
|
||||
|
||||
# TODO - WASM compile for embedding directly in HTML
|
||||
# - this may not be an option, sadly. might have to just port it to JS
|
||||
# TODO - option to add a caption based on the filename (for SVG)
|
||||
# TODO - load palettes from a file
|
||||
# TODO - PNG output
|
||||
@@ -36,11 +34,13 @@ def cli_main() -> None:
|
||||
PALETTE_HELP = "\n".join(
|
||||
[
|
||||
"PALETTE CHOICES",
|
||||
'\n'.join(textwrap.wrap(
|
||||
"\n".join(
|
||||
textwrap.wrap(
|
||||
", ".join(PALETTE_CHOICES),
|
||||
initial_indent=" ",
|
||||
subsequent_indent=" ",
|
||||
)),
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
HASH_CHOICES = ["md5", "sha1", "sha224", "sha256", "sha384", "sha512"]
|
||||
@@ -59,7 +59,9 @@ def cli_main() -> None:
|
||||
OUTPUT_TYPE_HELP = "OUTPUT TYPE (-y, --output-type)\n" + "\n".join(
|
||||
[f" {choice} - {desc}" for choice, desc in OUTPUT_TYPE_CHOICES.items()]
|
||||
)
|
||||
EPILOGUE = "\n\n".join([MATRIX_HELP, PALETTE_HELP, INPUT_TYPE_HELP, OUTPUT_TYPE_HELP])
|
||||
EPILOGUE = "\n\n".join(
|
||||
[MATRIX_HELP, PALETTE_HELP, INPUT_TYPE_HELP, OUTPUT_TYPE_HELP]
|
||||
)
|
||||
|
||||
progname: str = sys.argv[0]
|
||||
if progname.endswith("__main__.py"):
|
||||
@@ -175,13 +177,9 @@ def cli_main() -> None:
|
||||
matricizer: Matricizer
|
||||
match args.matrix:
|
||||
case "nibble":
|
||||
w, h = NibbleMatricizer.DIMENSIONS[args.hash]
|
||||
matricizer = NibbleMatricizer(w, h)
|
||||
matricizer = NibbleMatricizer()
|
||||
case "randomart":
|
||||
# 17x9 is what openssh uses
|
||||
# TODO - allow configuring dimensions, maybe
|
||||
w, h = RandomartMatricizer.DIMENSIONS[args.hash]
|
||||
matricizer = RandomartMatricizer(w, h)
|
||||
matricizer = RandomartMatricizer()
|
||||
case _:
|
||||
assert False, f"invalid args.matrix: {args.matrix}"
|
||||
|
||||
@@ -210,4 +208,3 @@ def cli_main() -> None:
|
||||
sys.stdout.write(output)
|
||||
else:
|
||||
args.out.write_text(output)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"All things that turn a hash into a matrix."
|
||||
import abc
|
||||
import re
|
||||
from typing import Mapping, Sequence
|
||||
|
||||
from .palettes import Palette, DEFAULT_PALETTES, GRADIENT_PALETTES, MULTICOLOR_PALETTES
|
||||
@@ -8,6 +9,27 @@ from .palettes import Palette, DEFAULT_PALETTES, GRADIENT_PALETTES, MULTICOLOR_P
|
||||
Matrix = Sequence[Sequence[int]]
|
||||
|
||||
|
||||
def detect_hash_algorithm(hash_or_algo: str | bytes) -> str | None:
|
||||
dimensions: Mapping[int, str] = {
|
||||
32: "md5",
|
||||
40: "sha1",
|
||||
56: "sha224",
|
||||
64: "sha256",
|
||||
96: "sha384",
|
||||
128: "sha512",
|
||||
}
|
||||
if isinstance(hash_or_algo, bytes):
|
||||
return dimensions.get(len(hash_or_algo) * 2)
|
||||
|
||||
hoa = hash_or_algo.lower()
|
||||
if re.match(r"^([0-9a-fA-F]{2})+$", hoa):
|
||||
return dimensions.get(len(hoa))
|
||||
elif hoa in list(dimensions.values()):
|
||||
return hoa
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class Matricizer(metaclass=abc.ABCMeta):
|
||||
"""
|
||||
The base Matricizer class.
|
||||
@@ -16,16 +38,6 @@ class Matricizer(metaclass=abc.ABCMeta):
|
||||
(inclusive). The method by which this is done is up to the matricizer.
|
||||
"""
|
||||
|
||||
def __init__(self, w: int, h: int) -> None:
|
||||
"""
|
||||
Create a new matricizer for the given dimensions.
|
||||
|
||||
:param w: the width of the output matrix.
|
||||
:param h: the height of hte output matrix.
|
||||
"""
|
||||
self.w = w
|
||||
self.h = h
|
||||
|
||||
@abc.abstractmethod
|
||||
def matricize(self, data: bytes) -> Matrix:
|
||||
"""
|
||||
@@ -35,16 +47,6 @@ class Matricizer(metaclass=abc.ABCMeta):
|
||||
:returns: the matrix converted from the hash data.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def choose_dimensions(hash: str) -> tuple[int, int]:
|
||||
"""
|
||||
Choose the dimensions for this matrix based on the hash algorithm.
|
||||
|
||||
:param hash: the hash algorithm being used.
|
||||
:returns: a width and height as a tuple.
|
||||
"""
|
||||
|
||||
def choose_palette(
|
||||
self, data: bytes, palettes: Mapping[str, Palette] | None = None
|
||||
) -> Palette:
|
||||
@@ -84,32 +86,31 @@ class NibbleMatricizer(Matricizer):
|
||||
:returns: the matrix converted from the hash data.
|
||||
"""
|
||||
|
||||
algo = detect_hash_algorithm(data)
|
||||
w, h = self.DIMENSIONS[algo]
|
||||
|
||||
nibbles = []
|
||||
for b in data:
|
||||
top = (b & 0xF0) >> 4
|
||||
bottom = b & 0x0F
|
||||
nibbles += [top, bottom]
|
||||
|
||||
if len(nibbles) != self.w * self.h:
|
||||
if len(nibbles) != w * h:
|
||||
raise ValueError(
|
||||
f"input data length ({len(nibbles)}) must match matrix dimensions "
|
||||
f"({self.w}x{self.h} = {self.w * self.h})"
|
||||
f"({w}x{h} = {w * h})"
|
||||
)
|
||||
|
||||
cols = []
|
||||
row = []
|
||||
for b in nibbles:
|
||||
row += [b]
|
||||
if len(row) == self.w:
|
||||
if len(row) == w:
|
||||
cols += [row]
|
||||
row = []
|
||||
|
||||
return cols
|
||||
|
||||
@staticmethod
|
||||
def choose_dimensions(hash: str) -> tuple[int, int]:
|
||||
return NibbleMatricizer.DIMENSIONS[hash]
|
||||
|
||||
def choose_palette(
|
||||
self, data: bytes, palettes: Mapping[str, Palette] | None = None
|
||||
) -> Palette:
|
||||
@@ -150,10 +151,12 @@ class RandomartMatricizer(Matricizer):
|
||||
:param data: the hash data to turn into a matrix.
|
||||
:returns: the matrix converted from the hash data.
|
||||
"""
|
||||
algo = detect_hash_algorithm(data)
|
||||
w, h = self.DIMENSIONS[algo]
|
||||
|
||||
rows = [[0] * self.w for _ in range(self.h)]
|
||||
c = self.w // 2
|
||||
r = self.h // 2
|
||||
rows = [[0] * w for _ in range(h)]
|
||||
c = w // 2
|
||||
r = h // 2
|
||||
for value in data:
|
||||
for _ in range(4):
|
||||
if value & 0x1:
|
||||
@@ -164,18 +167,14 @@ class RandomartMatricizer(Matricizer):
|
||||
r += 1
|
||||
else:
|
||||
r -= 1
|
||||
c = min(max(c, 0), self.w - 1)
|
||||
r = min(max(r, 0), self.h - 1)
|
||||
c = min(max(c, 0), w - 1)
|
||||
r = min(max(r, 0), h - 1)
|
||||
# max value is 0xf
|
||||
if rows[r][c] < 0xF:
|
||||
rows[r][c] += 1
|
||||
value >>= 2;
|
||||
value >>= 2
|
||||
return rows
|
||||
|
||||
@staticmethod
|
||||
def choose_dimensions(hash: str) -> tuple[int, int]:
|
||||
return RandomartMatricizer.DIMENSIONS[hash]
|
||||
|
||||
def choose_palette(
|
||||
self, data: bytes, palettes: Mapping[str, Palette] | None = None
|
||||
) -> Palette:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"Base color palette definitions."
|
||||
import abc
|
||||
from typing import Sequence
|
||||
|
||||
from .color import Color, HSLColor
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
"Colorhash writer classes"
|
||||
import abc
|
||||
|
||||
from .color import Color, ColorMatrix
|
||||
@@ -13,30 +14,47 @@ class Writer(metaclass=abc.ABCMeta):
|
||||
|
||||
@abc.abstractmethod
|
||||
def write(self, matrix: ColorMatrix) -> str:
|
||||
"Write the color matrix to a string."
|
||||
"""
|
||||
Write the color matrix to a string.
|
||||
|
||||
:param matrix: the color matrix to generate the SVG for.
|
||||
:returns: the full generated SVG as a string.
|
||||
"""
|
||||
|
||||
|
||||
class ANSIWriter(Writer):
|
||||
"""
|
||||
ANSI terminal writer. This will output a 24-bit true color string.
|
||||
"""
|
||||
def write(self, matrix: ColorMatrix) -> str:
|
||||
ESC = "\x1b"
|
||||
RESET = f"{ESC}[0m"
|
||||
C = "██"
|
||||
"""
|
||||
Write the color matrix to an ANSI string.
|
||||
|
||||
:param matrix: the color matrix to generate the SVG for.
|
||||
:returns: the full generated SVG as a string.
|
||||
"""
|
||||
esc = "\x1b"
|
||||
reset = f"{esc}[0m"
|
||||
c = "██"
|
||||
|
||||
def ansi_color(c: Color) -> str:
|
||||
c = c.to_rgb()
|
||||
return f"{ESC}[38;2;{round(c.r)};{round(c.g)};{round(c.b)}m"
|
||||
return f"{esc}[38;2;{round(c.r)};{round(c.g)};{round(c.b)}m"
|
||||
|
||||
out = ""
|
||||
for row in matrix:
|
||||
for col in row:
|
||||
out += ansi_color(col)
|
||||
out += C
|
||||
out += c
|
||||
out += "\n"
|
||||
out += RESET
|
||||
out += reset
|
||||
return out
|
||||
|
||||
|
||||
class SVGWriter(Writer):
|
||||
"""
|
||||
SVG string writer.
|
||||
"""
|
||||
def __init__(self, square_size: int) -> None:
|
||||
"""
|
||||
Create a new SVG writer that uses the given square size.
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
<svg width="256" height="160" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="32" height="32" fill="hsl(60.00,100.00%,40.00%)" />
|
||||
<rect x="32" y="0" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="64" y="0" width="32" height="32" fill="hsl(60.00,100.00%,6.67%)" />
|
||||
<rect x="96" y="0" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="128" y="0" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="160" y="0" width="32" height="32" fill="hsl(60.00,100.00%,13.33%)" />
|
||||
<rect x="192" y="0" width="32" height="32" fill="hsl(60.00,100.00%,40.00%)" />
|
||||
<rect x="224" y="0" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="0" y="32" width="32" height="32" fill="hsl(60.00,100.00%,10.00%)" />
|
||||
<rect x="32" y="32" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="64" y="32" width="32" height="32" fill="hsl(60.00,100.00%,16.67%)" />
|
||||
<rect x="96" y="32" width="32" height="32" fill="hsl(60.00,100.00%,6.67%)" />
|
||||
<rect x="128" y="32" width="32" height="32" fill="hsl(60.00,100.00%,3.33%)" />
|
||||
<rect x="160" y="32" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="192" y="32" width="32" height="32" fill="hsl(60.00,100.00%,43.33%)" />
|
||||
<rect x="224" y="32" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="0" y="64" width="32" height="32" fill="hsl(60.00,100.00%,23.33%)" />
|
||||
<rect x="32" y="64" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="64" y="64" width="32" height="32" fill="hsl(60.00,100.00%,3.33%)" />
|
||||
<rect x="96" y="64" width="32" height="32" fill="hsl(60.00,100.00%,43.33%)" />
|
||||
<rect x="128" y="64" width="32" height="32" fill="hsl(60.00,100.00%,33.33%)" />
|
||||
<rect x="160" y="64" width="32" height="32" fill="hsl(60.00,100.00%,30.00%)" />
|
||||
<rect x="192" y="64" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="224" y="64" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="0" y="96" width="32" height="32" fill="hsl(60.00,100.00%,50.00%)" />
|
||||
<rect x="32" y="96" width="32" height="32" fill="hsl(60.00,100.00%,10.00%)" />
|
||||
<rect x="64" y="96" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="96" y="96" width="32" height="32" fill="hsl(60.00,100.00%,40.00%)" />
|
||||
<rect x="128" y="96" width="32" height="32" fill="hsl(60.00,100.00%,40.00%)" />
|
||||
<rect x="160" y="96" width="32" height="32" fill="hsl(60.00,100.00%,3.33%)" />
|
||||
<rect x="192" y="96" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="224" y="96" width="32" height="32" fill="hsl(60.00,100.00%,30.00%)" />
|
||||
<rect x="0" y="128" width="32" height="32" fill="hsl(60.00,100.00%,36.67%)" />
|
||||
<rect x="32" y="128" width="32" height="32" fill="hsl(60.00,100.00%,16.67%)" />
|
||||
<rect x="64" y="128" width="32" height="32" fill="hsl(60.00,100.00%,26.67%)" />
|
||||
<rect x="96" y="128" width="32" height="32" fill="hsl(60.00,100.00%,20.00%)" />
|
||||
<rect x="128" y="128" width="32" height="32" fill="hsl(60.00,100.00%,16.67%)" />
|
||||
<rect x="160" y="128" width="32" height="32" fill="hsl(60.00,100.00%,50.00%)" />
|
||||
<rect x="192" y="128" width="32" height="32" fill="hsl(60.00,100.00%,43.33%)" />
|
||||
<rect x="224" y="128" width="32" height="32" fill="hsl(60.00,100.00%,0.00%)" />
|
||||
<rect x="0" y="0" width="32" height="32" fill="hsl(30.00,100.00%,6.67%)" />
|
||||
<rect x="32" y="0" width="32" height="32" fill="hsl(30.00,100.00%,36.67%)" />
|
||||
<rect x="64" y="0" width="32" height="32" fill="hsl(30.00,100.00%,10.00%)" />
|
||||
<rect x="96" y="0" width="32" height="32" fill="hsl(30.00,100.00%,0.00%)" />
|
||||
<rect x="128" y="0" width="32" height="32" fill="hsl(30.00,100.00%,0.00%)" />
|
||||
<rect x="160" y="0" width="32" height="32" fill="hsl(30.00,100.00%,23.33%)" />
|
||||
<rect x="192" y="0" width="32" height="32" fill="hsl(30.00,100.00%,0.00%)" />
|
||||
<rect x="224" y="0" width="32" height="32" fill="hsl(30.00,100.00%,26.67%)" />
|
||||
<rect x="0" y="32" width="32" height="32" fill="hsl(30.00,100.00%,16.67%)" />
|
||||
<rect x="32" y="32" width="32" height="32" fill="hsl(30.00,100.00%,3.33%)" />
|
||||
<rect x="64" y="32" width="32" height="32" fill="hsl(30.00,100.00%,30.00%)" />
|
||||
<rect x="96" y="32" width="32" height="32" fill="hsl(30.00,100.00%,36.67%)" />
|
||||
<rect x="128" y="32" width="32" height="32" fill="hsl(30.00,100.00%,10.00%)" />
|
||||
<rect x="160" y="32" width="32" height="32" fill="hsl(30.00,100.00%,36.67%)" />
|
||||
<rect x="192" y="32" width="32" height="32" fill="hsl(30.00,100.00%,33.33%)" />
|
||||
<rect x="224" y="32" width="32" height="32" fill="hsl(30.00,100.00%,3.33%)" />
|
||||
<rect x="0" y="64" width="32" height="32" fill="hsl(30.00,100.00%,26.67%)" />
|
||||
<rect x="32" y="64" width="32" height="32" fill="hsl(30.00,100.00%,20.00%)" />
|
||||
<rect x="64" y="64" width="32" height="32" fill="hsl(30.00,100.00%,43.33%)" />
|
||||
<rect x="96" y="64" width="32" height="32" fill="hsl(30.00,100.00%,6.67%)" />
|
||||
<rect x="128" y="64" width="32" height="32" fill="hsl(30.00,100.00%,3.33%)" />
|
||||
<rect x="160" y="64" width="32" height="32" fill="hsl(30.00,100.00%,13.33%)" />
|
||||
<rect x="192" y="64" width="32" height="32" fill="hsl(30.00,100.00%,3.33%)" />
|
||||
<rect x="224" y="64" width="32" height="32" fill="hsl(30.00,100.00%,50.00%)" />
|
||||
<rect x="0" y="96" width="32" height="32" fill="hsl(30.00,100.00%,10.00%)" />
|
||||
<rect x="32" y="96" width="32" height="32" fill="hsl(30.00,100.00%,23.33%)" />
|
||||
<rect x="64" y="96" width="32" height="32" fill="hsl(30.00,100.00%,0.00%)" />
|
||||
<rect x="96" y="96" width="32" height="32" fill="hsl(30.00,100.00%,23.33%)" />
|
||||
<rect x="128" y="96" width="32" height="32" fill="hsl(30.00,100.00%,43.33%)" />
|
||||
<rect x="160" y="96" width="32" height="32" fill="hsl(30.00,100.00%,13.33%)" />
|
||||
<rect x="192" y="96" width="32" height="32" fill="hsl(30.00,100.00%,16.67%)" />
|
||||
<rect x="224" y="96" width="32" height="32" fill="hsl(30.00,100.00%,6.67%)" />
|
||||
<rect x="0" y="128" width="32" height="32" fill="hsl(30.00,100.00%,3.33%)" />
|
||||
<rect x="32" y="128" width="32" height="32" fill="hsl(30.00,100.00%,50.00%)" />
|
||||
<rect x="64" y="128" width="32" height="32" fill="hsl(30.00,100.00%,16.67%)" />
|
||||
<rect x="96" y="128" width="32" height="32" fill="hsl(30.00,100.00%,30.00%)" />
|
||||
<rect x="128" y="128" width="32" height="32" fill="hsl(30.00,100.00%,10.00%)" />
|
||||
<rect x="160" y="128" width="32" height="32" fill="hsl(30.00,100.00%,16.67%)" />
|
||||
<rect x="192" y="128" width="32" height="32" fill="hsl(30.00,100.00%,13.33%)" />
|
||||
<rect x="224" y="128" width="32" height="32" fill="hsl(30.00,100.00%,36.67%)" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Reference in New Issue
Block a user