Skip to content

Commit

Permalink
Bump version to 1.0.4
Browse files Browse the repository at this point in the history
Signed-off-by: Ali Sherief <alihsherief@linuxmail.org>
  • Loading branch information
ZenulAbidin committed Nov 27, 2020
1 parent 7422322 commit 5acd253
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 99 deletions.
4 changes: 4 additions & 0 deletions bip39validator/InitUniqResult.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def __init__(self, res, threshold):
self.lines = res['lines']
self.threshold = threshold

def __len__(self):
prefix_list = regroup_prefix(self.words, self.lines, self.threshold)
return len(prefix_list) # number of groups

def similargroup(self, prefix):
"""Gets the list of words and lines beginning with ``prefix``
Expand Down
3 changes: 3 additions & 0 deletions bip39validator/LevDistResult.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ def __init__(self, res, words_sorted, lines_sorted, threshold):
self.lines_sorted = lines_sorted
self.threshold = threshold

def __len__(self):
return len(self.split)

def _index_pair(self, first, second):
return (first, second)

Expand Down
3 changes: 3 additions & 0 deletions bip39validator/MaxLengthResult.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def __init__(self, res, words_sorted, lines_sorted, threshold):
self.words = [a for a in words_sorted]
self.lines = [a for a in lines_sorted]

def __len__(self):
return len(self.words_long)

def getwords_long(self):
"""Gets the words that are longer than the threshold tested against.
Expand Down
104 changes: 51 additions & 53 deletions bip39validator/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def version_str():


def abort(debug):
if log_file:
log_file.close()
if debug:
logerror("Debug mode on, entering pdb")
pdb.set_trace()
Expand All @@ -55,12 +57,11 @@ def abort(debug):
logerror("Aborting")
exit(1)


log_file = None
args = None


def main():
log_file = None
try:
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
description='BIP39 wordlist validator')
Expand Down Expand Up @@ -103,8 +104,9 @@ def main():
if args.output:
try:
absout = abspath(args.output)
if not args.quiet:
logdefault("Attempting to open log file {} for writing".format(absout))
# Set the ascii flag if desired before printing this
setargs(None, args)
logdefault("Attempting to open log file {} for writing".format(absout))
log_file = open(absout, 'w')
setargs(log_file, args)
except OSError as e:
Expand All @@ -129,26 +131,24 @@ def main():
abort(args.debug)

try:
if not args.quiet:
logdefault("Reading wordlist file {}".format(args.input))
logdefault("Reading wordlist file {}".format(args.input))
with open(args.input) as f:
bip39 = BIP39WordList(desc=f"{args.input}", handle=f)
# word_line_arr = to_wordline_array(contents2list(s))
# loginfo("{} words read".format(len(word_line_arr.word_list))
loginfo("{} words read".format(len(bip39)))
except OSError as e:
logerror("Cannot read {}: {}".format(e.filename,
e.strerror))
abort(args.debug)

tally = 0
total = 4
total = 4 - int(args.no_lev_dist) - int(args.no_init_uniq)\
- int(args.no_max_length)

def check_validity_warnings(validity):
if not validity.is_sorted and not args.quiet:
if not validity.is_sorted:
logwarning('Wordlist is not sorted. It is recommended to sort the wordlist \
before publishing it.')
if not validity.has_2048_words and not args.quiet:
if not validity.has_2048_words:
logwarning('Wordlist has {} words. Exactly 2048 words are needed to map \
each word to an 11-bit value 1-to-1.'.format(validity.num_words))

Expand Down Expand Up @@ -182,28 +182,26 @@ def check_validity_warnings(validity):
kwargs = progressbar('Computing Levenshtein distance', tup[0],
tup[1], tup[2], **kwargs)
bip39._test_lev_distance_2(kwargs)
if not args.quiet:
loginfo("No word pairs with Levenshtein distance less than {}" \
loginfo("No word pairs with Levenshtein distance less than {}" \
.format(args.lev_dist))
tally += 1
loginfo("Levenshtein distance test succeeded")
except ValidationFailed as e:
if not args.quiet:
lev_dist = e.status_obj
word_pairs = lev_dist.getwordpairs_lt()
logerror("{} word pairs with Levenshtein distance less than {}\n" \
lev_dist = e.status_obj
word_pairs = lev_dist.getwordpairs_lt()
logerror("{} word pairs with Levenshtein distance less than {}\n" \
.format(len(word_pairs), args.lev_dist))
for i in range(1, args.lev_dist):
words_list = [*zip(lev_dist.getwordpairs_eq(i), lev_dist.getlinepairs_eq(i))]
logerror("{} word pairs with Levenshtein distance *equal* to {}:" \
for i in range(1, args.lev_dist):
words_list = [*zip(lev_dist.getwordpairs_eq(i), lev_dist.getlinepairs_eq(i))]
logerror("{} word pairs with Levenshtein distance *equal* to {}:" \
.format(len(words_list), i))
for words, lines in words_list:
logerror(" \"{}\" (line {}) <--> \"{}\" (line {})" \
for words, lines in words_list:
logerror(" \"{}\" (line {}) <--> \"{}\" (line {})" \
.format(words[0], lines[0], words[1], lines[1]))
logerror("")
logerror("{} total words below minimum Levenshtein distance".format(len(
word_pairs)))
logerror("Levenshtein distance test failed")
logerror("")
logerror("{} total words below minimum Levenshtein distance".format(len(
word_pairs)))
logerror("Levenshtein distance test failed")

logdefault("Finished performing Levenshtein distance test")
separator()
Expand All @@ -220,22 +218,21 @@ def check_validity_warnings(validity):
tally += 1
loginfo("Unique initial characters test succeeded")
except ValidationFailed as e:
if not args.quiet:
similar = e.status_obj
# Filter out groups with just one word in them as those are unique
groups = {k: v for (k, v) in similar.similargroup_all().items() if
similar = e.status_obj
# Filter out groups with just one word in them as those are unique
groups = {k: v for (k, v) in similar.similargroup_all(args.init_uniq).items() if
len(v) > 1}
logerror("{} groups of similar words (by {} initial characters)\n" \
logerror("{} groups of similar words (by {} initial characters)\n" \
.format(len(groups.items()), args.init_uniq))
for pre, group in groups:
logerror("Similar words with prefix \"{}\":").format(pre)
for wordline in group:
logerror(" \"{}\" (line {})".format(wordline[0], wordline[1]))
logerror("")
logerror("{} total similar words".format(len(groups.keys())))
logerror("Unique initial characters test failed")
logdefault("Finished unique initial characters test")
separator()
for pre, group in groups.items():
logerror("Similar words with prefix \"{}\":".format(pre))
for wordline in group:
logerror(" \"{}\" (line {})".format(wordline[0], wordline[1]))
logerror("")
logerror("{} total similar words".format(len(groups.keys())))
logerror("Unique initial characters test failed")
logdefault("Finished unique initial characters test")
separator()

if not args.no_max_length:
logdefault("Performing maximum word length test")
Expand All @@ -249,20 +246,21 @@ def check_validity_warnings(validity):
tally += 1
loginfo("Maximum word length test succeeded")
except ValidationFailed as e:
if not args.quiet:
lengths = e.status_obj
words = lengths.getwords_gt()
lines = lengths.getlines_gt()
logerror("Words longer than {} characters:".format(args.max_length))
for word, line in [*zip(words, lines)]:
logerror(" \"{}\" (line {})", word, line)
logerror("{} words longer than {} characters".format(len(lengths),
args.max_length))
logerror("Maximum word length test failed")
logdefault("Finished maximum word length test")
separator()
lengths = e.status_obj
words = lengths.getwords_gt(args.max_length)
lines = lengths.getlines_gt(args.max_length)
logerror("Words longer than {} characters:".format(args.max_length))
for word, line in [*zip(words, lines)]:
logerror(" \"{}\" (line {})".format(word, line))
logerror("{} words longer than {} characters".format(len(lengths),
args.max_length))
logerror("Maximum word length test failed")
logdefault("Finished maximum word length test")
separator()

logdefault("{} of {} test_vectors passed".format(tally, total))
logdefault("{} of {} checks passed".format(tally, total))
if log_file:
log_file.close()
exit(0)
except Exception as e:
print("Got unknown exception {}: {}".format(type(e), str(e)))
Expand Down
2 changes: 1 addition & 1 deletion bip39validator/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.0.3"
__version__ = "1.0.4"
98 changes: 56 additions & 42 deletions bip39validator/internal/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,86 +24,100 @@
from rich.markdown import Markdown
from rich.progress import track

class ParamsInternal:
def __init__(self, ascii, log_file, quiet):
self.ascii = ascii
self.log_file = log_file
self.quiet = quiet

# These functions are not intended for use outside the main program.

# Utility function to print an error message
def logerror(*args):
if not ascii:
error_console.print(*["[bold red]ERROR: [/bold red]" + s for s in args])
else:
print(*["ERROR: " + s for s in args], sep="\n", file=sys.stderr)
if not params.quiet:
if not params.ascii:
error_console.print(*["[bold red]ERROR: [/bold red]" + s for s in args])
else:
print(*["ERROR: " + s for s in args], sep="\n", file=sys.stderr)

if log_file:
print(*["ERROR: " + s for s in args], sep="\n", file=log_file)
if params.log_file:
params.log_file.write("\n".join(["ERROR: " + s for s in args])+"\n")


# Utility function to print a warning message
def logwarning(*args):
if not ascii:
error_console.print(*["[bold yellow]WARNING: [/bold yellow]" + s for s
in args], sep="\n")
else:
print(*["WARNING: " + s for s in args], sep="\n", file=sys.stderr)
if not params.quiet:
if not params.ascii:
error_console.print(*["[bold yellow]WARNING: [/bold yellow]" + s for s
in args], sep="\n")
else:
print(*["WARNING: " + s for s in args], sep="\n", file=sys.stderr)

if log_file:
print(*["WARNING: " + s for s in args], sep="\n", file=log_file)
if params.log_file:
params.log_file.write("\n".join(["WARNING: " + s for s in args])+"\n")


# Utility function to print an informational message
def loginfo(*args):
if not ascii:
info_console.print(*["[green]INFO: [/green]" + s for s in args], sep="\n")
else:
print(*["INFO: " + s for s in args], sep="\n", file=sys.stdout)
if not params.quiet:
if not params.ascii:
info_console.print(*["[green]INFO: [/green]" + s for s in args], sep="\n")
else:
print(*["INFO: " + s for s in args], sep="\n", file=sys.stdout)

if log_file:
print(*["INFO: " + s for s in args], sep="\n", file=log_file)
if params.log_file:
params.log_file.write("\n".join(["INFO: " + s for s in args])+"\n")


# Utility function to print a normal default message
def logdefault(*args):
if not ascii:
info_console.print(*args, sep="\n")
else:
print(*args, sep="\n", file=sys.stdout)

if log_file:
print(*args, sep="\n", file=log_file)
if not params.quiet:
if not params.ascii:
info_console.print(*args, sep="\n")
else:
print(*args, sep="\n", file=sys.stdout)

if params.log_file:
params.log_file.write("\n".join(args)+"\n")

# Utility function to print a progress bar that repeatedly calls a worker
# function that takes it's own `kwargs` and returns its updated `kwargs` for
# the next iteration.
def progressbar(desc, low, high, func, **kwargs):
if not ascii:
for i in track(range(low, high), description=desc):
kwargs = func(i, **kwargs)
return kwargs
if not params.quiet:
if not params.ascii:
for i in track(range(low, high), description=desc):
kwargs = func(i, **kwargs)
return kwargs
else:
print(desc + ", please wait...")
for i in range(low, high):
kwargs = func(i, **kwargs)
return kwargs
else:
print(desc + ", please wait...")
for i in range(low, high):
kwargs = func(i, **kwargs)
return kwargs


def separator():
if not ascii:
info_console.print(Markdown('---'))
else:
print("=" * 10, file=sys.stdout)
if not params.quiet:
if not params.ascii:
info_console.print(Markdown('---'))
else:
print("=" * 10, file=sys.stdout)

if log_file:
print("=" * 10, file=log_file)
if params.log_file:
params.log_file.write("=" * 10 + "\n")

log_file = None
ascii = False
params = ParamsInternal(False, None, False)

def setargs(log, args):
log_file = log
ascii = args.ascii
params.log_file = log
params.ascii = args.ascii
params.quiet = args.quiet


if not ascii:
if not params.ascii:
error_console = Console(file=sys.stderr)
info_console = Console(file=sys.stdout)
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from setuptools import setup, find_namespace_packages
from setuptools import setup, find_packages
import os.path

with open(os.path.join('.', 'README.rst'), encoding='utf-8') as f:
long_description = f.read()

setup(
name='bip39validator',
version='1.0.3',
version='1.0.4',
long_description=long_description,
long_description_content_type='text/x-rst',
packages=find_namespace_packages(where='.'),
packages=find_packages(),
package_dir={'bip39validator': 'bip39validator'},
url='https://github.com/ZenulAbidin/bip39validator',
license='MIT',
Expand Down

0 comments on commit 5acd253

Please sign in to comment.