Pythonistaで指紋認証


概要

Pythonistaで指紋認証をしただけ

コード

touch_id.py

# coding: utf-8
from objc_util import *
import threading

NSBundle = ObjCClass('NSBundle')
LocalAuthentication = NSBundle.bundleWithPath_(
    '/System/Library/Frameworks/LocalAuthentication.framework')
LocalAuthentication.load()
LAContext = ObjCClass('LAContext')

class AuthFailedException(Exception):
    pass

class AuthCancelledException(AuthFailedException):
    pass

class AuthTimeoutException(AuthFailedException):
    pass

class AuthNotAvailableException(AuthFailedException):
    pass

class AuthFallbackMechanismSelectedException(AuthFailedException):
    pass


def is_available():
    context = LAContext.new().autorelease()
    return bool(context.canEvaluatePolicy_error_(1, None))


def authenticate(reason='', allow_passcode=True, timeout=None):
    if not is_available():
        raise AuthNotAvailableException('Touch ID is not available.')
    policy = 2 if allow_passcode else 1
    context = LAContext.new().autorelease()
    event = threading.Event()
    result = {}

    def callback(_cmd, success, _error):
        result['success'] = success
        if _error:
            error = ObjCInstance(_error)
            result['error'] = error
        event.set()

    handler = ObjCBlock(
        callback, restype=None, argtypes=[c_void_p, c_bool, c_void_p])
    context.evaluatePolicy_localizedReason_reply_(policy, reason, handler)
    if not event.wait(timeout):
        context.invalidate()
        raise AuthTimeoutException('Timeout')
    success = result.get('success', False)
    error = result.get('error')
    if success:
        return True
    elif error:
        error_code = error.code()
        if error_code == -2:
            raise AuthCancelledException('Cancelled by user')
        elif error_code == -3:
            raise AuthFallbackMechanismSelectedException(
                'Fallback authentication mechanism selected')
        else:
            desc = error.localizedDescription() or 'Unknown error'
            raise AuthFailedException(desc)
    else:
        raise AuthFailedException('Unknown error')


# 例
def main():
    try:
        reason = 'We need you fingerprint.'
        authenticate(reason,allow_passcode=True)
        print('Success!')
    except AuthFailedException as e:
        print(e)


if __name__ == '__main__':
    main()

感想

Pythonista強い!