Added disconnect to TwythonStreamer, more tests, update example
* Stream and Twython core tests * Import TwythonStreamError from twython See more in 2.10.1 section of HISTORY.rst
This commit is contained in:
parent
815393cc33
commit
c8b1202880
9 changed files with 122 additions and 55 deletions
|
|
@ -22,4 +22,7 @@ __version__ = '2.10.1'
|
|||
|
||||
from .twython import Twython
|
||||
from .streaming import TwythonStreamer
|
||||
from .exceptions import TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
from .exceptions import (
|
||||
TwythonError, TwythonRateLimitError, TwythonAuthError,
|
||||
TwythonStreamError
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,17 +2,15 @@ from .endpoints import twitter_http_status_codes
|
|||
|
||||
|
||||
class TwythonError(Exception):
|
||||
"""
|
||||
Generic error class, catch-all for most Twython issues.
|
||||
Special cases are handled by TwythonAuthError & TwythonRateLimitError.
|
||||
"""Generic error class, catch-all for most Twython issues.
|
||||
Special cases are handled by TwythonAuthError & TwythonRateLimitError.
|
||||
|
||||
Note: Syntax has changed as of Twython 1.3. To catch these,
|
||||
you need to explicitly import them into your code, e.g:
|
||||
Note: Syntax has changed as of Twython 1.3. To catch these,
|
||||
you need to explicitly import them into your code, e.g:
|
||||
|
||||
from twython import (
|
||||
TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
)
|
||||
"""
|
||||
from twython import (
|
||||
TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
)"""
|
||||
def __init__(self, msg, error_code=None, retry_after=None):
|
||||
self.error_code = error_code
|
||||
|
||||
|
|
@ -30,18 +28,16 @@ class TwythonError(Exception):
|
|||
|
||||
|
||||
class TwythonAuthError(TwythonError):
|
||||
""" Raised when you try to access a protected resource and it fails due to
|
||||
some issue with your authentication.
|
||||
"""
|
||||
"""Raised when you try to access a protected resource and it fails due to
|
||||
some issue with your authentication."""
|
||||
pass
|
||||
|
||||
|
||||
class TwythonRateLimitError(TwythonError):
|
||||
""" Raised when you've hit a rate limit.
|
||||
"""Raised when you've hit a rate limit.
|
||||
|
||||
The amount of seconds to retry your request in will be appended
|
||||
to the message.
|
||||
"""
|
||||
The amount of seconds to retry your request in will be appended
|
||||
to the message."""
|
||||
def __init__(self, msg, error_code, retry_after=None):
|
||||
if isinstance(retry_after, int):
|
||||
msg = '%s (Retry after %d seconds)' % (msg, retry_after)
|
||||
|
|
@ -49,5 +45,5 @@ class TwythonRateLimitError(TwythonError):
|
|||
|
||||
|
||||
class TwythonStreamError(TwythonError):
|
||||
"""Test"""
|
||||
"""Raised when an invalid response from the Stream API is received"""
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -55,41 +55,48 @@ class TwythonStreamer(object):
|
|||
self.user = StreamTypes.user
|
||||
self.site = StreamTypes.site
|
||||
|
||||
self.connected = False
|
||||
|
||||
def _request(self, url, method='GET', params=None):
|
||||
"""Internal stream request handling"""
|
||||
self.connected = True
|
||||
retry_counter = 0
|
||||
|
||||
method = method.lower()
|
||||
func = getattr(self.client, method)
|
||||
|
||||
def _send(retry_counter):
|
||||
try:
|
||||
if method == 'get':
|
||||
response = func(url, params=params, timeout=self.timeout)
|
||||
else:
|
||||
response = func(url, data=params, timeout=self.timeout)
|
||||
except requests.exceptions.Timeout:
|
||||
self.on_timeout()
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
self.on_error(response.status_code, response.content)
|
||||
|
||||
if self.retry_count and (self.retry_count - retry_counter) > 0:
|
||||
time.sleep(self.retry_in)
|
||||
retry_counter += 1
|
||||
_send(retry_counter)
|
||||
|
||||
return response
|
||||
|
||||
response = _send(retry_counter)
|
||||
|
||||
for line in response.iter_lines():
|
||||
if line:
|
||||
while self.connected:
|
||||
try:
|
||||
self.on_success(json.loads(line))
|
||||
except ValueError:
|
||||
raise TwythonStreamError('Response was not valid JSON, \
|
||||
unable to decode.')
|
||||
if method == 'get':
|
||||
response = func(url, params=params, timeout=self.timeout)
|
||||
else:
|
||||
response = func(url, data=params, timeout=self.timeout)
|
||||
except requests.exceptions.Timeout:
|
||||
self.on_timeout()
|
||||
else:
|
||||
if response.status_code != 200:
|
||||
self.on_error(response.status_code, response.content)
|
||||
|
||||
if self.retry_count and (self.retry_count - retry_counter) > 0:
|
||||
time.sleep(self.retry_in)
|
||||
retry_counter += 1
|
||||
_send(retry_counter)
|
||||
|
||||
return response
|
||||
|
||||
while self.connected:
|
||||
response = _send(retry_counter)
|
||||
|
||||
for line in response.iter_lines():
|
||||
if not self.connected:
|
||||
break
|
||||
if line:
|
||||
try:
|
||||
self.on_success(json.loads(line))
|
||||
except ValueError:
|
||||
raise TwythonStreamError('Response was not valid JSON, \
|
||||
unable to decode.')
|
||||
|
||||
def on_success(self, data):
|
||||
"""Called when data has been successfull received from the stream
|
||||
|
|
@ -161,3 +168,6 @@ class TwythonStreamer(object):
|
|||
|
||||
def on_timeout(self):
|
||||
return
|
||||
|
||||
def disconnect(self):
|
||||
self.connected = False
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class TwythonStreamerTypesStatuses(object):
|
|||
self.streamer._request(url, params=params)
|
||||
|
||||
def firehose(self, **params):
|
||||
"""Stream statuses/filter
|
||||
"""Stream statuses/firehose
|
||||
|
||||
Accepted params found at:
|
||||
https://dev.twitter.com/docs/api/1.1/get/statuses/firehose
|
||||
|
|
|
|||
|
|
@ -388,11 +388,12 @@ class Twython(object):
|
|||
yield tweet
|
||||
|
||||
try:
|
||||
kwargs['page'] = 2 if not 'page' in kwargs else (int(kwargs['page']) + 1)
|
||||
if not 'since_id' in kwargs:
|
||||
kwargs['since_id'] = (int(content['statuses'][0]['id_str']) + 1)
|
||||
except (TypeError, ValueError):
|
||||
raise TwythonError('Unable to generate next page of search results, `page` is not a number.')
|
||||
|
||||
for tweet in self.searchGen(search_query, **kwargs):
|
||||
for tweet in self.search_gen(search_query, **kwargs):
|
||||
yield tweet
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue