#!/usr/bin/env python
"""
Module which produces readble name from 256-bit of random data
(i.e. sha-256 hash)


"""
MAXWORDLEN=12
#
# Modules which contain problablity dictionaries
# generated by genmarkov script
#
from surname_hash import surname
from female_hash import female
from male_hash import male
#
import operator

gendernames=[male,female]

class RandError(Exception):
	"""
		Raised if all bits are exhausted
	"""
	pass

def getrandom(count):
	"""
		extracts neccessary amount of randomness (non neccessary
		integer number of bits) from given input
	"""
	global data
	if data==0:
		raise RandError("No more random data")
	data,r=divmod(data,count)
	return r
def morerandom():
	"""
		Checks if there are some random bits left
	"""
	global data
	return data!=0

def mkword(x):
	"""
		Compuites word from given  dictionary.
		Randomly chooses first and second letter and
		with probabilities of their occurence after whicespace
		and then chooses next letter until space is encountered
	"""
	count=0
	global MAXWORDLEN
	first=x[' ']
	count=reduce(operator.add,map(len,first.itervalues()))
	i=getrandom(count)
	for letter in sorted(first):
		if i<len(first[letter]):
			word=letter+first[letter][i]
			break
		i-=len(first[letter])
	while word[-1]!=' ':
		y=x[word[-2]][word[-1]]
		word+=y[getrandom(len(y))]
		if len(word)>= MAXWORDLEN:
			word+=" "
			break
	return word.title()

def mkname(hash):
	"""
		Gets 64 hexadecimal digits and computes name from it
	"""
	global data
	if (len(hash)<64):
		raise ValueError("To few random data: "+hash)
	data=int(hash,16)
	x=gendernames[getrandom(2)]
	name=mkword(surname)
	more=True
	while more:
		try:
			name+=mkword(x)
		except RandError:
			more= False
	return name.strip()

if __name__ == "__main__":
	#
	# Test main routine which reads random data from
	#
	import sys
	from base64 import b16encode
	from os import urandom
	if len(sys.argv)>1 and sys.argv[1].isdigit():
		for i in xrange(0,int(sys.argv[1])):
			d=b16encode(urandom(32))
			try:
				print mkname(d)
			except RandError:
				print "Not enough random: "+d
	else:
		for i in xrange(0,20):
			d=b16encode(urandom(32))
			print d,mkname(d)

Set maximal word length limit
Set maximal word length limit
