Skip to content

Commit c93556a

Browse files
authored
Merge pull request djacobs#189 from microamp/feature/minor-refactoring
Minor enhancements
2 parents cee961b + 0bf8c76 commit c93556a

File tree

1 file changed

+54
-53
lines changed

1 file changed

+54
-53
lines changed

apns.py

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,31 @@
5252
ENHANCED_NOTIFICATION_COMMAND = 1
5353

5454
NOTIFICATION_FORMAT = (
55-
'!' # network big-endian
56-
'B' # command
57-
'H' # token length
58-
'32s' # token
59-
'H' # payload length
60-
'%ds' # payload
61-
)
55+
'!' # network big-endian
56+
'B' # command
57+
'H' # token length
58+
'32s' # token
59+
'H' # payload length
60+
'%ds' # payload
61+
)
6262

6363
ENHANCED_NOTIFICATION_FORMAT = (
64-
'!' # network big-endian
65-
'B' # command
66-
'I' # identifier
67-
'I' # expiry
68-
'H' # token length
69-
'32s' # token
70-
'H' # payload length
71-
'%ds' # payload
72-
)
64+
'!' # network big-endian
65+
'B' # command
66+
'I' # identifier
67+
'I' # expiry
68+
'H' # token length
69+
'32s' # token
70+
'H' # payload length
71+
'%ds' # payload
72+
)
7373

7474
ERROR_RESPONSE_FORMAT = (
75-
'!' # network big-endian
76-
'B' # command
77-
'B' # status
78-
'I' # identifier
79-
)
75+
'!' # network big-endian
76+
'B' # command
77+
'B' # status
78+
'I' # identifier
79+
)
8080

8181
TOKEN_LENGTH = 32
8282
ERROR_RESPONSE_LENGTH = 6
@@ -140,7 +140,7 @@ def unpacked_uint_big_endian(bytes):
140140
Returns an unsigned int from a packed big-endian (network) byte array
141141
"""
142142
return unpack('>I', bytes)[0]
143-
143+
144144
@staticmethod
145145
def unpacked_char_big_endian(bytes):
146146
"""
@@ -230,7 +230,7 @@ def _connect(self):
230230
sys.exc_clear()
231231
else:
232232
raise
233-
233+
234234
self.connection_alive = True
235235
_logger.debug("%s APNS connection established" % self.__class__.__name__)
236236

@@ -255,14 +255,14 @@ def write(self, string):
255255
if self.enhanced: # nonblocking socket
256256
self._last_activity_time = time.time()
257257
_, wlist, _ = select.select([], [self._connection()], [], WAIT_WRITE_TIMEOUT_SEC)
258-
258+
259259
if len(wlist) > 0:
260260
length = self._connection().sendall(string)
261261
if length == 0:
262262
_logger.debug("sent length: %d" % length) #DEBUG
263263
else:
264264
_logger.warning("write socket descriptor is not ready after " + str(WAIT_WRITE_TIMEOUT_SEC))
265-
265+
266266
else: # blocking socket
267267
return self._connection().write(string)
268268

@@ -298,7 +298,7 @@ def __init__(self, payload_size):
298298

299299
class Payload(object):
300300
"""A class representing an APNs message payload"""
301-
def __init__(self, alert=None, badge=None, sound=None, category=None, custom={}, content_available=False,
301+
def __init__(self, alert=None, badge=None, sound=None, category=None, custom=None, content_available=False,
302302
mutable_content=False):
303303
super(Payload, self).__init__()
304304
self.alert = alert
@@ -334,7 +334,8 @@ def dict(self):
334334
d.update({'mutable-content': 1})
335335

336336
d = { 'aps': d }
337-
d.update(self.custom)
337+
if self.custom:
338+
d.update(self.custom)
338339
return d
339340

340341
def json(self):
@@ -465,20 +466,20 @@ class GatewayConnection(APNsConnection):
465466
"""
466467
A class that represents a connection to the APNs gateway server
467468
"""
468-
469+
469470
def __init__(self, use_sandbox=False, **kwargs):
470471
super(GatewayConnection, self).__init__(**kwargs)
471472
self.server = (
472473
'gateway.push.apple.com',
473474
'gateway.sandbox.push.apple.com')[use_sandbox]
474475
self.port = 2195
475-
if self.enhanced == True: #start error-response monitoring thread
476+
if self.enhanced == True: #start error-response monitoring thread
476477
self._last_activity_time = time.time()
477-
478+
478479
self._send_lock = threading.RLock()
479480
self._error_response_handler_worker = None
480481
self._response_listener = None
481-
482+
482483
self._sent_notifications = collections.deque(maxlen=SENT_BUFFER_QTY)
483484

484485
def _init_error_response_handler_worker(self):
@@ -515,7 +516,7 @@ def _get_enhanced_notification(self, token_hex, payload, identifier, expiry):
515516
notification = pack(fmt, ENHANCED_NOTIFICATION_COMMAND, identifier, expiry,
516517
TOKEN_LENGTH, token, len(payload), payload)
517518
return notification
518-
519+
519520
def send_notification(self, token_hex, payload, identifier=0, expiry=0):
520521
"""
521522
in enhanced mode, send_notification may return error response from APNs if any
@@ -524,7 +525,7 @@ def send_notification(self, token_hex, payload, identifier=0, expiry=0):
524525
self._last_activity_time = time.time()
525526
message = self._get_enhanced_notification(token_hex, payload,
526527
identifier, expiry)
527-
528+
528529
for i in range(WRITE_RETRY):
529530
try:
530531
with self._send_lock:
@@ -534,16 +535,16 @@ def send_notification(self, token_hex, payload, identifier=0, expiry=0):
534535
break
535536
except socket_error as e:
536537
delay = 10 + (i * 2)
537-
_logger.exception("sending notification with id:" + str(identifier) +
538-
" to APNS failed: " + str(type(e)) + ": " + str(e) +
538+
_logger.exception("sending notification with id:" + str(identifier) +
539+
" to APNS failed: " + str(type(e)) + ": " + str(e) +
539540
" in " + str(i+1) + "th attempt, will wait " + str(delay) + " secs for next action")
540541
time.sleep(delay) # wait potential error-response to be read
541542

542543
else:
543544
self.write(self._get_notification(token_hex, payload))
544-
545+
545546
def _make_sure_error_response_handler_worker_alive(self):
546-
if (not self._error_response_handler_worker
547+
if (not self._error_response_handler_worker
547548
or not self._error_response_handler_worker.is_alive()):
548549
self._init_error_response_handler_worker()
549550
TIMEOUT_SEC = 10
@@ -557,45 +558,45 @@ def _make_sure_error_response_handler_worker_alive(self):
557558
def send_notification_multiple(self, frame):
558559
self._sent_notifications += frame.get_notifications(self)
559560
return self.write(frame.get_frame())
560-
561+
561562
def register_response_listener(self, response_listener):
562563
self._response_listener = response_listener
563-
564+
564565
def force_close(self):
565566
if self._error_response_handler_worker:
566567
self._error_response_handler_worker.close()
567-
568+
568569
def _is_idle_timeout(self):
569570
TIMEOUT_IDLE = 30
570571
return (time.time() - self._last_activity_time) >= TIMEOUT_IDLE
571-
572+
572573
class ErrorResponseHandlerWorker(threading.Thread):
573574
def __init__(self, apns_connection):
574575
threading.Thread.__init__(self, name=self.__class__.__name__)
575576
self._apns_connection = apns_connection
576577
self._close_signal = False
577-
578+
578579
def close(self):
579580
self._close_signal = True
580-
581+
581582
def run(self):
582583
while True:
583584
if self._close_signal:
584585
_logger.debug("received close thread signal")
585586
break
586-
587+
587588
if self._apns_connection._is_idle_timeout():
588589
idled_time = (time.time() - self._apns_connection._last_activity_time)
589590
_logger.debug("connection idle after %d secs" % idled_time)
590591
break
591-
592+
592593
if not self._apns_connection.connection_alive:
593594
time.sleep(1)
594595
continue
595-
596+
596597
try:
597598
rlist, _, _ = select.select([self._apns_connection._connection()], [], [], WAIT_READ_TIMEOUT_SEC)
598-
599+
599600
if len(rlist) > 0: # there's some data from APNs
600601
with self._apns_connection._send_lock:
601602
buff = self._apns_connection.read(ERROR_RESPONSE_LENGTH)
@@ -611,23 +612,23 @@ def run(self):
611612
if len(buff) == 0:
612613
_logger.warning("read socket got 0 bytes data") #DEBUG
613614
self._apns_connection._disconnect()
614-
615+
615616
except socket_error as e: # APNS close connection arbitrarily
616617
_logger.exception("exception occur when reading APNS error-response: " + str(type(e)) + ": " + str(e)) #DEBUG
617618
self._apns_connection._disconnect()
618619
continue
619-
620+
620621
time.sleep(0.1) #avoid crazy loop if something bad happened. e.g. using invalid certificate
621-
622+
622623
self._apns_connection._disconnect()
623624
_logger.debug("error-response handler worker closed") #DEBUG
624-
625+
625626
def _resend_notifications_by_id(self, failed_identifier):
626627
fail_idx = Util.getListIndexFromID(self._apns_connection._sent_notifications, failed_identifier)
627628
#pop-out success notifications till failed one
628629
self._resend_notification_by_range(fail_idx+1, len(self._apns_connection._sent_notifications))
629630
return
630-
631+
631632
def _resend_notification_by_range(self, start_idx, end_idx):
632633
self._apns_connection._sent_notifications = collections.deque(itertools.islice(self._apns_connection._sent_notifications, start_idx, end_idx))
633634
_logger.info("resending %s notifications to APNS" % len(self._apns_connection._sent_notifications)) #DEBUG
@@ -643,7 +644,7 @@ def _resend_notification_by_range(self, start_idx, end_idx):
643644
class Util(object):
644645
@classmethod
645646
def getListIndexFromID(this_class, the_list, identifier):
646-
return next(index for (index, d) in enumerate(the_list)
647+
return next(index for (index, d) in enumerate(the_list)
647648
if d['id'] == identifier)
648649
@classmethod
649650
def convert_error_response_to_dict(this_class, error_response_tuple):

0 commit comments

Comments
 (0)