#!/usr/bin/env python2 """ namegen.py ========== --------------------- random name generator --------------------- :Authors: Elena ``of Valhalla'' Grandi, Diego Roversi :Date: 2011-09-11 :Copyright: 2011 Elena Grandi, Diego Roversi :Version: 0.20110911 :Manual Section: 1 SYNOPSIS -------- namegen.py (-s )|(-l ) [-S ] [-n ] DESCRIPTION ----------- OPTIONS ------- -s , --stats= Load rules from . -l , --list= Generate rules from the files in . -S , --save_stats= Save stats in . -n , --number= Generate names (0 to generate no name). -c , --context= Use characters of context in the stats. -h, --help Show an help message. LICENSE ------- """ import json import optparse import sys import random class Stats: def __init__(self,context): """""" self.stats = {} self.context = context def _increment_stats(self,cont,key): if cont in self.stats: if key in self.stats[cont]: self.stats[cont][key] += 1 else: self.stats[cont][key] = 1 else: self.stats[cont] = {key: 1} def read_names(self,fp): """Calculate stats from a list of names in a file-like object.""" for name in fp.readlines(): name = name.decode('utf-8') for i in xrange(min(self.context,len(name))): self._increment_stats(name[0:i],name[i]) for i in xrange(self.context,len(name)): self._increment_stats(name[i-self.context:i],name[i]) def load_stats(self,fp): """Load stats from a yaml in a string or file-like object""" self.stats = json.load(fp) self.context = max([len(k) for k in self.stats.keys()]) def save_stats(self,fp): """Save stats in yaml to a file-like object""" json.dump(self.stats,fp) def generate_name(self): """Generate a name following the stats""" name = '' c = '' while c != '\n': if len(name) <= self.context: cont = name else: cont = name[-self.context:] chars = ''.join([k*self.stats[cont][k] for k in self.stats[cont]]) c = random.choice(chars) name += c return name def main(): parser = optparse.OptionParser() parser.add_option('--stats','-s') parser.add_option('--list','-l') parser.add_option('--save-stats','-S') parser.add_option('--number','-n') parser.add_option('--context','-c') opt, arg = parser.parse_args() if opt.stats == None and opt.list == None: parser.print_help() sys.exit(1) try: mystats = Stats(int(opt.context)) except TypeError: mystats = Stats(3) need_list = True try: fp = open(opt.stats) except IOError: sys.stderr.write("Could not open "+opt.stats+" for reading.\n") except TypeError: pass else: try: mystats.load_stats(fp) need_list = False except ValueError: sys.stderr.write(opt.stats+" is not a valid stats file.\n") finally: fp.close() if need_list: try: fp = open(opt.list) except IOError: sys.stderr.write("Could not open "+opt.list+" for reading.\n") sys.exit(1) except TypeError: parser.print_help() sys.exit(1) else: try: mystats.read_names(fp) except IOError: sys.stderr.write(opt.list+" is not a valid name list file.\n") sys.exit(1) finally: fp.close() try: fp = open(opt.save_stats,'wb') except TypeError: pass except IOError: sys.stderr.write("Warning: could not save stats data on file "+ opt.save_stats+"\n") else: try: mystats.save_stats(fp) except IOError: sys.stderr.write("Warning: could not save stats data on file "+ opt.save_stats+"\n") finally: fp.close() try: n = int(opt.number) except (TypeError, ValueError): n = 1 for i in xrange(n): print mystats.generate_name(), if __name__ == '__main__': main()