solution_118_04.py

#!/usr/bin/python3
# ====================================================================
# passworld vault 04 - utilities
# ====================================================================

import time


msg0 = 'Welcome to my Password Vault program.'

msg1 = 'v0.1'

msg2 = 'Password Vault  ' + msg1

msg3 = '''\
Searches are case-insensitive substring matches.
All entries that match are returned as a list of
entries.'''

msg4 = '''\
My password vault is a dictionary. It is stored on disk as an
ecrypted JSON data structure. Encryption and decryption use a
symmetrical key (the same key). This key is generated from a
password you create and enter.
   DO NOT FORGET THIS PASSWORD.
If you do, the data can not be recoved.

My Password Vault allows you to have multiple vaults. Each can
vault is a different file and can have the same or different
password. The program start with a default vault. You then
select which vault to access. While the program is running you
can switch to a different vault. I would suggest you keep the
entries to less than 60 to 80 entries per vault.

You may also dump a vault to a CVS file which is not
encrypted.

Each entry is given a unique (integer) ID. This can
speed up processing because it eliminates duplicate
matching entries. Deleted entry IDs are never reused.'''

# --------------------------------------------------------------------
# ----- display each line is a multi-line string
# --------------------------------------------------------------------

def _display_message_indented(msg,indent=''):

    lines = msg.split('\n')
    for line in lines:
        print(indent + line)

# --------------------------------------------------------------------
# ---- display message
# --------------------------------------------------------------------

def display_message(i,indent=None):

    msg = None
    
    if i == 0:
        msg = msg0
    elif i == 1:
        msg = msg1
    elif i == 2:
        msg = msg2
    elif i == 3:
        msg = msg3
    elif i == 4:
        msg = msg4

    if msg is None:
        return None
        
    if indent is not None:
        _display_message_indented(msg,indent) 
        return i
        
    print(msg)
    return i

# --------------------------------------------------------------------
# ---- return message
# --------------------------------------------------------------------

def return_message(i):

    msg = ''

    if i == 0:
        msg = msg0
    elif i == 1:
        msg = msg1
    elif i == 2:
        msg = msg2
    elif i == 3:
        msg = msg3
    elif i == 4:
        msg = msg4

    return msg

# --------------------------------------------------------------------
# ---- current date (string)
# --------------------------------------------------------------------

def current_date():

    t = time.time()
    
    return time.strftime('%B %d, %Y',time.localtime(t))
    

# -------------------------------------------------------------------
# ---- renumber entry IDs
# ---- this function can be used to eliminate gaps in the range
# ---- of IDs if you feel there are to many.
# -------------------------------------------------------------------

def renumber_vault_ids(vault):

    id_count = 0
    
    for e in vault["entries"]:
        id_count += 1
        e["id"] = id_count
            
    return id_count

# -------------------------------------------------------------------
# ---- return entries that match an id
# ---- test if an entry's id matches
# -------------------------------------------------------------------

def search_for_id(vault,id):

    lst = []
    
    for e in vault["entries"]:
        if id == e["id"]:
            lst.append(ee)
            
    return lst

# -------------------------------------------------------------------
# ---- return entries that have 'name' match pat (string)
# ---- (case insensitive search for a substring)
# ----
# ---- for each entry
# ---- test if there is a substring match in 'name'
# -------------------------------------------------------------------

def search_for_name(vault,pat):

    lst = []

    if not pat:
        return lst

    lpat = pat.lower()

    for e in vault["entries"]:
        lnam = e["name"].lower()
        idx = lnam.find(lpat)
        if idx >= 0:
            lst.append(e)

    return lst


# -------------------------------------------------------------------
# ---- return entries that have 'note' matchs pat (string)
# ---- (case insensitive search for a substring)
# ----
# ---- (notes are optional)
# ---- for each entry
# ---- test if the dictionary key 'note' exists in vault
# ---- test if there is a note (not '' or None)
# ---- test if there is a substring match in 'note'
# -------------------------------------------------------------------

def search_for_note(vault,pat):

    lst = []

    if not pat:
        return lst

    lpat = pat.lower()
    
    for e in vault["entries"]:
        if "note" in e:
            if e["note"]:
                lnot = e["note"].lower()
                idx = lnot.find(lpat)
                if idx >= 0:
                    lst.append(e)

    return lst
    
   
# -------------------------------------------------------------------
# ---- main (test utilities)
# -------------------------------------------------------------------

if __name__ == '__main__':

    import password_vault_01_db as db
    
    vault = db.test_vault_1

    print('----display  messages----------------------------')

    print()
    display_message(0)
    display_message(1)
    display_message(3)
    print()
    
    print('----current date---------------------------------')

    print(current_date())

    print('----name match \'A\'-------------------------------')
    
    lst = search_for_name(vault,'A')
    print(f'lst-len = {len(lst)}')
    for e in lst:
        print(f'entry   = {e["name"]}')


    print('----name match \'zon\'-----------------------------')
    
    lst = search_for_name(vault,'zon')
    print(f'lst-len = {len(lst)}')
    for e in lst:
        print(f'entry   = {e["name"]}')

    print('----note match \'fur\'-----------------------------')
    
    lst = search_for_note(vault,'fur')
    print(f'lst-len = {len(lst)}')
    for e in lst:
        print(f'entry   = {e["note"]}')