Source code for COMPS.CredentialPrompt

import getpass
import os
import platform
import sys
from future.utils import with_metaclass
from abc import ABCMeta, abstractmethod


[docs]class CredentialPrompt(with_metaclass(ABCMeta, object)): """ Abstract definition for our credential prompts. """
[docs] @abstractmethod def prompt(self): """ The prompt method will ask a user for COMPS usernme and password. It should return a duct containing the username and password keys and values :return: """ pass
[docs]class ConsoleCredentialPrompt(CredentialPrompt): """ A simple console based credential prompt """
[docs] def prompt(self): username = input("Username: ") password = getpass.getpass() return dict(Username=username.strip(), Password=password)
[docs]class TKCredentialPrompt(CredentialPrompt): """ A TK based credential prompt """
[docs] def prompt(self): if sys.version_info[0] == 2: import Tkinter as tk else: import tkinter as tk master = tk.Tk() master.title('COMPS Login') master["padx"] = 12 master["pady"] = 10 input_frame = tk.Frame(master) input_frame.grid(row=0) username = tk.StringVar(master) password = tk.StringVar(master) ret_ok = tk.BooleanVar(master) tk.Label(input_frame, text='Username', padx=10).grid(row=0) usrbox = tk.Entry(input_frame, textvariable=username) usrbox.grid(row=0, column=1) usrbox.focus() tk.Label(input_frame, text='Password', padx=10, pady=5).grid(row=1) pwdbox = tk.Entry(input_frame, show='*', textvariable=password) pwdbox.grid(row=1, column=1) def inputchanged(*args): if username.get() and password.get(): okay_button.config(state='normal') else: okay_button.config(state='disabled') def onok(evt=None): if okay_button.cget('state') in ['normal', 'active']: ret_ok.set(True) master.destroy() def oncancel(evt=None): username.set('') password.set('') ret_ok.set(False) master.destroy() username.trace("w", inputchanged) password.trace("w", inputchanged) button_frame = tk.Frame(master) button_frame["pady"] = 4 button_frame.grid(row=1) button_frame.columnconfigure(0, weight=1, pad=6) button_frame.columnconfigure(1, weight=1, pad=6) okay_button = tk.Button(button_frame, command=onok, text='OK', state="disabled", width=10) okay_button.grid(row=0, column=0) tk.Button(button_frame, command=oncancel, text='Cancel', width=10).grid(row=0, column=1) master.bind('<Return>', onok) master.bind('<Escape>', oncancel) # reposition to the middle of the screen master.update_idletasks() w = master.winfo_screenwidth() h = master.winfo_screenheight() size = tuple(int(_) for _ in master.geometry().split('+')[0].split('x')) x = w / 2 - size[0] / 2 y = h / 2 - size[1] / 2 master.geometry("%dx%d+%d+%d" % (size + (x, y))) # make sure the dialog is in the front # if platform.system() != 'Darwin': # master.lift() if platform.system() != 'Darwin': master.lift() else: # .lift() apparently doesn't work on OSX... try this instead os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''') master.mainloop() if not ret_ok.get(): raise RuntimeError('User canceled attempt to get security credentials.') if len(username.get()) == 0 or len(password.get()) == 0: return None else: return {'Username': username.get(), 'Password': password.get()}
[docs]def get_credential_prompt(): """ Determines the appropriate CredentialPrompt. If TK is available, we use that, otherwise we fallback to Console based login. :return: CredentialPrompt factory """ try: if sys.version_info[0] == 2: import Tkinter as tk else: import tkinter as tk # attempt to initialize tk to test if we have a display. This mainly applies to linux systems where # tk is installed but we are running in a headless session such as through SSH testwin = tk.Tk() testwin.destroy() return TKCredentialPrompt() except: return ConsoleCredentialPrompt()