Implement the card request loop in connect() in the Smartcard_Reader base class and move all the gory details into _internal_connect to be implemented in the subclasses

This commit is contained in:
Henryk Plötz 2010-02-27 15:37:19 +01:00
parent f6f305317a
commit d073fc662e
1 changed files with 38 additions and 15 deletions

View File

@ -13,10 +13,32 @@ class Smartcard_Reader(object):
return []
list_readers = classmethod(list_readers)
def connect(self):
"Create a connection to this reader"
_CONNECT_NO_CARD = object()
_CONNECT_MUTE_CARD = object()
_CONNECT_DONE = object()
def _internal_connect(self):
"""Must implement the iterator protocol and yield
one of self._CONNECT_NO_CARD, self._CONNECT_MUTE_CARD or self._CONNECT_DONE.
The iterator will not be called again after yielding _CONNECT_DONE, so it must
clean itself up before that."""
raise NotImplementedError, "Please implement in a sub-class"
def connect(self):
have_card = False
printed = False
for result in self._internal_connect():
if result is self._CONNECT_DONE:
have_card = True
break
elif result is self._CONNECT_MUTE_CARD:
print "Card is mute or absent. Please retry."
elif result is self._CONNECT_NO_CARD:
if not printed:
print "Please insert card ..."
printed = True
return have_card
def get_ATR(self):
"Get the ATR of the inserted card as a binary string"
raise NotImplementedError, "Please implement in a sub-class"
@ -38,12 +60,14 @@ class PCSC_Reader(Smartcard_Reader):
name = property(lambda self: self._name, None, None, "The human readable name of the reader")
def list_readers(cls):
return [ (str(r), cls(r)) for r in smartcard.System.readers() ]
try:
return [ (str(r), cls(r)) for r in smartcard.System.readers() ]
except smartcard.pcsc.PCSCExceptions.EstablishContextException:
return []
list_readers = classmethod(list_readers)
def connect(self):
def _internal_connect(self):
unpatched = False
printed = False
while True:
try:
if not unpatched:
@ -53,24 +77,23 @@ class PCSC_Reader(Smartcard_Reader):
self._cardservice = cardrequest.waitforcard()
self._cardservice.connection.connect()
break
del cardrequest
yield self._CONNECT_DONE
except TypeError:
unpatched = True
except (KeyboardInterrupt, SystemExit):
raise
except smartcard.Exceptions.CardRequestException:
if sys.exc_info()[1].message.endswith("Command timeout."):
if not printed:
print "Please insert card ..."
printed = True
yield self._CONNECT_NO_CARD
else:
raise
except smartcard.Exceptions.CardRequestTimeoutException:
if not printed:
print "Please insert card ..."
printed = True
yield self._CONNECT_NO_CARD
except smartcard.Exceptions.NoCardException:
print "Card is mute or absent. Please retry."
yield self._CONNECT_MUTE_CARD
except smartcard.Exceptions.CardConnectionException:
yield self._CONNECT_MUTE_CARD
def get_ATR(self):
return smartcard.util.toASCIIString(self._cardservice.connection.getATR())
@ -148,10 +171,10 @@ class ACR122_Reader(Smartcard_Reader):
if ord(response[2]) > 0:
return True
def connect(self):
# FIXME Add loop or something similar to PCSC_Reader.connect
def _internal_connect(self):
self._parent.connect()
self.pn532_acquire_card()
yield self._CONNECT_DONE
def get_ATR(self):
# FIXME Properly implement for PC/SC version 2