Utiliser le TouchID depuis un script python

Avoir une belle machine avec un TouchID, savoir pisser quelques lignes de code en python.
Rien de plus pour se donner les moyens d’accéder au TouchID depuis un script python :

Reprenons le script précédent, celui qui envoie des notifications à OS X Notification Center.


#!/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/python
# -*- coding: utf-8 -*-

import ctypes, sys
from AppKit import NSImage
from Foundation import NSUserNotification
from Foundation import NSUserNotificationCenter
from Foundation import NSUserNotificationDefaultSoundName
from optparse import OptionParser

from LocalAuthentication import LAContext
from LocalAuthentication import LAPolicyDeviceOwnerAuthenticationWithBiometrics, LAPolicyDeviceOwnerAuthentication

kLAPolicy = LAPolicyDeviceOwnerAuthentication

c = ctypes.cdll.LoadLibrary(None)

dispatch_semaphore_create = c.dispatch_semaphore_create
dispatch_semaphore_create.restype = ctypes.c_void_p
dispatch_semaphore_create.argtypes = [ctypes.c_int]

dispatch_semaphore_wait = c.dispatch_semaphore_wait
dispatch_semaphore_wait.restype = ctypes.c_long
dispatch_semaphore_wait.argtypes = [ctypes.c_void_p, ctypes.c_uint64]

dispatch_semaphore_signal = c.dispatch_semaphore_signal
dispatch_semaphore_signal.restype = ctypes.c_long
dispatch_semaphore_signal.argtypes = [ctypes.c_void_p]

def is_available():
context = LAContext.new()
return context.canEvaluatePolicy_error_(kLAPolicy, None)[0]

def authenticate(reason='lancer la notification'):
context = LAContext.new()

can_evaluate = context.canEvaluatePolicy_error_(kLAPolicy, None)[0]
if not can_evaluate:
raise Exception("Touch ID isn't available on this machine")

sema = dispatch_semaphore_create(0)

# we can't reassign objects from another scope, but we can modify them
res = {'success': False, 'error': None}

def cb(_success, _error):
res['success'] = _success
if _error:
res['error'] = _error.localizedDescription()
dispatch_semaphore_signal(sema)

context.evaluatePolicy_localizedReason_reply_(kLAPolicy, reason, cb)
dispatch_semaphore_wait(sema, sys.maxint)

if res['error']:
raise Exception(res['error'])

return res['success']


def _nsimage_from_file(filename, dimensions=None, template=None):
#Take a path to an image file and return an NSImage object.
try:
with open(filename):
pass
except IOError: # literal file path didn't work -- try to locate image based on main script path
try:
from __main__ import __file__ as main_script_path
main_script_path = os.path.dirname(main_script_path)
filename = os.path.join(main_script_path, filename)
except ImportError:
pass
with open(filename): # file doesn't exist
pass # otherwise silently errors in NSImage which isn't helpful for debugging
image = NSImage.alloc().initByReferencingFile_(filename)
image.setScalesWhenResized_(True)
image.setSize_((20, 20) if dimensions is None else dimensions)
if not template is None:
image.setTemplate_(template)
return image

def main():

success = authenticate()

parser = OptionParser(usage='%prog -t TITLE -m MESSAGE')
parser.add_option('-t', '--title', action='store', default='A title')
parser.add_option('-s', '--subtitle', action='store', default='...')
parser.add_option('-m', '--message', action='store', default='...')
parser.add_option('-i', '--image', action='store', default=None)
parser.add_option('--no-sound', action='store_false', default=True,
dest='sound')

options, args = parser.parse_args()

notification = NSUserNotification.alloc().init()
notification.setTitle_(options.title)
notification.setSubtitle_(options.subtitle)
if options.image:
image = _nsimage_from_file(options.image)
notification.setContentImage_(image)
notification.setInformativeText_(options.message)
if options.sound:
notification.setSoundName_(NSUserNotificationDefaultSoundName)

center = NSUserNotificationCenter.defaultUserNotificationCenter()
center.deliverNotification_(notification)

if __name__ == '__main__':
main()

Publié dans Non classé.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *