Skip to content

Instantly share code, notes, and snippets.

@loliee
Last active May 13, 2020 15:58
Show Gist options
  • Save loliee/3c03e755f65baf2c42981a05849653fc to your computer and use it in GitHub Desktop.
Save loliee/3c03e755f65baf2c42981a05849653fc to your computer and use it in GitHub Desktop.
A simple naming assistant.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Need a first name ? Curl that script and start a brainstorming session
# 🇫🇷 https://www.data.gouv.fr/fr/datasets/liste-de-prenoms/
import os
import sys
import random
import csv
import pickle
import hashlib
import subprocess
import urllib.request
from argparse import ArgumentParser
C = {
'blue': '\033[94m',
'green': '\033[92m',
'yellow': '\033[93m',
'red': '\033[91m',
'bold': '\033[1m',
'reset': '\033[0m'
}
CSV_URL = 'https://www.data.gouv.fr/fr/datasets/r/55cd803a-998d-4a5c-9741-4cd0ee0a7699'
CSV_SHA256 = 'e3d77a4ceab1e477eeafb410e7390393cec2ba8a4b9dd764e31e7a2b2b79b187'
def sha256sum(filepath):
'''sha256sum a file'''
blocksize = 65536
hasher = hashlib.sha256()
with open(filepath, 'rb') as afile:
buf = afile.read(blocksize)
while len(buf) > 0:
hasher.update(buf)
buf = afile.read(blocksize)
return hasher.hexdigest()
def format_csv_line(obj):
'''Convert csv line to utf-8 dictionary'''
key = obj[0]
meta = {
'gender': obj[1],
'origin': obj[2],
'freq': float(obj[3])
}
return key, meta
class BabyNaming(object):
def __init__(self, args):
self._args = args
self._app_dir = os.path.join(os.environ.get('HOME'), '.babynaming')
self._csv_file = os.path.join(self._app_dir, 'base.csv')
self._init_app_dir()
self._is_say()
if self._args.print_only:
self._load_csv()
self._create_dbe()
elif self._args.session and os.path.exists(self._get_session_path()):
self._load_db()
else:
if not self._args.session:
self._args.session = input('\nEnter a session name: ')
if os.path.exists(self._get_session_path()):
self._load_db()
else:
print('{}Create new session file "{}" {}'.format(
C['blue'], self._get_session_path(), C['reset']
))
self._load_csv()
self._create_dbe()
self._save()
def _load_csv(self):
data = {}
with open(self._csv_file, 'r', encoding='ISO-8859-1') as csvfile:
reader = csv.reader(csvfile, delimiter=';')
next(reader)
for line in reader:
key, meta = format_csv_line(line)
data[key] = meta
self._db = data
def _load_db(self):
print('{}Load session file "{}" {}'.format(
C['blue'], self._get_session_path(), C['reset']
))
self._db = pickle.load(open(self._get_session_path(), 'rb'))
self._create_dbe()
def _is_say(self):
try:
subprocess.check_output(
'hash say',
shell=True,
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError:
print('{}"say" command is not available {}'.format(
C['yellow'], C['reset']
))
self._args.voice = None
def _init_app_dir(self):
if not os.path.exists(self._app_dir):
os.mkdir(self._app_dir)
if not os.path.exists(self._csv_file):
print('{}Download "{}" to "{}"{}'.format(
C['blue'], CSV_URL, self._csv_file, C['reset']
))
urllib.request.urlretrieve(CSV_URL, self._csv_file)
if sha256sum(self._csv_file) != CSV_SHA256:
print('{}CSV checksum is incorrect "{}""{}'.format(
C['red'], self._csv_file, C['reset']
))
def _create_dbe(self):
self._dbe = {
k: {'gender': v['gender'],
'origin': v['origin'],
'freq': v['freq']}
for k, v in self._db.items() if self._filter_key(k)
}
def _get_session_path(self):
return os.path.join(self._app_dir, self._args.session + '.pkl')
def _save(self):
with open(self._get_session_path(), 'wb+') as dbf:
pickle.dump(
self._db, dbf, pickle.HIGHEST_PROTOCOL
)
def _filter_key(self, key):
ret = True
if self._args.origin and (
self._args.origin not in self._db[key]['origin']):
ret = False
if self._args.gender and (
self._args.gender not in self._db[key]['gender']):
ret = False
return ret
def _print_all(self):
names = self._dbe.keys()
names.sort()
for name in names:
self._print(name)
def _print(self, name):
print('\n{}{}\n{}{}\nfreq: {}{}{}\norigin: {}{}{}\n{}'.format(
C['bold'], name.capitalize(), '-' * len(name), C['reset'],
C['green'], self._db[name]['freq'], C['reset'],
C['blue'], self._db[name]['origin'], C['reset'],
'-' * (len(self._dbe[name]['origin']) + 8)
))
def _say(self, name):
if self._args.voice:
subprocess.Popen(
'say --quality=127 --rate=0.01 -v {} "{}"'.format(
self._args.voice, name
), shell=True
)
def _count(self):
print('Still {}{}{}{} names'.format(
C['bold'], C['red'], len(self._dbe.keys()), C['reset']
))
def _get_answer(self, name):
while True:
answer = input('Keep this name ? (y/n) ? ')
if answer == 'n':
del self._db[name]
del self._dbe[name]
self._save()
break
elif answer == 'y':
self._dbe[name]['viewed'] = True
break
def start(self):
'''This can be long :/'''
if self._args.print_only:
self._print_all()
sys.exit(0)
while True:
names = [k for k, v in self._dbe.items() if 'viewed' not in v]
if names == []:
print('\n{}Your selection:\n - {}{}'.format(
C['bold'], C['reset'],
'\n - '.join(self._dbe.keys())
))
sys.exit(0)
name = random.choice(names)
self._print(name)
self._say(name)
self._get_answer(name)
self._count()
def main():
global C
parser = ArgumentParser(
description='Play and record a baby naming session. CTRL-C to exit.'
)
parser.add_argument(
'-s', '--session', dest='session', default=None,
help='Session file name, saved in ~/.babynaming directory.'
)
parser.add_argument(
'-g', '--gender', dest='gender', default=None,
help='Filter on gender (m|f).'
)
parser.add_argument(
'-o', '--origin', dest='origin', default=None,
help='Filter on origin (french|english|portuguese|...).'
)
parser.add_argument(
'-v', '--voice', dest='voice', default=None,
help='Voice name, will enable vocal reading with "say" command.'
)
parser.add_argument(
'-p', '--print-only', dest='print_only', default=None,
action='store_true',
help='Print all names and exit.'
)
parser.add_argument(
'--no-color', dest='no_color', default=None, action='store_true',
help='Disable color display'
)
args = parser.parse_args()
if args.no_color:
C = {k: '' for k, v in C.items()}
try:
babynamingparty = BabyNaming(args)
babynamingparty.start()
except KeyboardInterrupt:
print('{}\nExit...{}'.format(C['yellow'], C['reset']))
if __name__ == '__main__':
main()
@loliee
Copy link
Author

loliee commented Apr 5, 2018

Install

curl -s -o babynaming.py https://gist.githubusercontent.com/loliee/3c03e755f65baf2c42981a05849653fc/raw/43f5abfdd1d91ac1f63e36b50f2023634022c05e/babynaming.py && chmod u+x babynaming.py

Dependency free, should be executed as a non privileged user.

Screenshot

screen shot 2018-04-05 at 4 17 02 pm

screen shot 2018-04-05 at 4 20 28 pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment