Commit 2bcf7d4c authored by Josh Roesslein's avatar Josh Roesslein
Browse files

Added logging support into tweepy.

parent 6fed3248
......@@ -19,6 +19,10 @@ during upgrade will be listed here.
get_authorization_url() now takes a boolean that when
true uses the "sign in with twitter" flow.
See http://apiwiki.twitter.com/Sign-in-with-Twitter
+ Logging
+ Added TweepyLogger interface which allows applications
to collect log messages from Tweepy for debugging purposes.
+ Dummy, console, and file loggers available
+ Examples
+ Appengine demo (oauth)
+ Documentation of each method in api.py
......
......@@ -13,6 +13,7 @@ from . api import API
from . cache import Cache, MemoryCache, FileCache, MemCache
from . auth import BasicAuthHandler, OAuthHandler
from . streaming import Stream, StreamListener
from . logging import TweepyLogger, DummyLogger, ConsoleLogger, FileLogger
# Global, unauthenticated instance of API
api = API()
......
......@@ -8,6 +8,7 @@ import mimetypes
from . binder import bind_api
from . error import TweepError
from . auth import BasicAuthHandler, OAuthHandler
from . logging import DummyLogger
from tweepy.parsers import *
......@@ -15,7 +16,7 @@ class API(object):
"""Twitter API"""
def __init__(self, auth_handler=None, host='twitter.com', cache=None,
secure=False, api_root='', validate=True):
secure=False, api_root='', validate=True, logger=DummyLogger()):
# you may access these freely
self.auth_handler = auth_handler
self.host = host
......@@ -23,6 +24,7 @@ class API(object):
self.cache = cache
self.secure = secure
self.validate = validate
self.logger = logger
# not a good idea to touch these
self._username = None
......
......@@ -17,10 +17,16 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
if require_auth and not api.auth_handler:
raise TweepError('Authentication required!')
# Log some useful infomation
api.logger.debug('Starting request...')
api.logger.debug(' path: %s' % path)
api.logger.debug(' method: %s' % method)
# check for post_data parameter
if 'post_data' in kargs:
post_data = kargs['post_data']
del kargs['post_data']
api.logger.debug(' post data: %s' % post_data)
else:
post_data = None
......@@ -30,6 +36,7 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
del kargs['headers']
else:
headers = {}
api.logger.debug(' headers: %s' % headers)
# build parameter dict
if allowed_param:
......@@ -51,6 +58,7 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
if len(args) > 0 or len(kargs) > 0:
raise TweepError('This method takes no parameters!')
parameters = None
api.logger.debug(' parameters: %s' % parameters)
# Build url with parameters
if parameters:
......@@ -67,7 +75,10 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
# Apply authentication
if api.auth_handler:
api.auth_handler.apply_auth(scheme + _host + url, method, headers, parameters)
api.auth_handler.apply_auth(
scheme + _host + url,
method, headers, parameters
)
# Check cache if caching enabled and method is GET
if api.cache and method == 'GET':
......@@ -80,6 +91,7 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
result._api = api
else:
cache_result._api = api
api.logger.debug("Cache hit!")
return cache_result
# Open connection
......@@ -94,6 +106,9 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
# Get response
resp = conn.getresponse()
api.logger.debug('Received response...')
api.logger.debug(' headers: %s' % resp.getheaders())
api.logger.debug(' status code: %s' % resp.status)
# If an error was returned, throw an exception
if resp.status != 200:
......@@ -101,12 +116,14 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
error_msg = parse_error(resp.read())
except Exception:
error_msg = "Twitter error response: status code = %s" % resp.status
api.logger.error(' Error: %s' % error_msg)
raise TweepError(error_msg)
# Pass returned body into parser and return parser output
try:
out = parser(resp.read(), api)
except Exception:
api.logger.error(" parse error!")
raise TweepError("Failed to parse returned data")
conn.close()
......@@ -126,6 +143,9 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
# store result in cache
if api.cache and method == 'GET':
api.cache.store(url, out)
api.logger.debug(" caching result")
api.logger.debug('request done.')
return out
......
# Tweepy
# Copyright 2009 Joshua Roesslein
# See LICENSE
class TweepyLogger(object):
DEBUG = 1
WARNING = 2
ERROR = 3
def debug(self, message):
"""Output a debug log message"""
self.log(TweepyLogger.DEBUG, message)
def warning(self, message):
"""Output warning log message"""
self.log(TweepyLogger.WARNING, message)
def error(self, message):
"""Output error log message"""
self.log(TweepyLogger.ERROR, message)
def log(self, level, message):
"""Implement this method to handle log messages"""
raise NotImplementedError
def format(self, message):
"""Override this method to apply custom formating of messages"""
return message
class DummyLogger(TweepyLogger):
"""This logger just discards log messages"""
def log(self, level, message):
return
class ConsoleLogger(TweepyLogger):
"""Outputs log messages to stdout"""
def __init__(self, active_log_level=TweepyLogger.DEBUG):
self.active_log_level = active_log_level
def log(self, level, message):
if level <= self.active_log_level:
print message
class FileLogger(TweepyLogger):
"""Outputs log message to file"""
def __init__(self, filepath, active_log_level=TweepyLogger.DEBUG):
self.active_log_level = active_log_level
self.file = open(filepath, 'w')
def log(self, level, message):
if level <= self.active_log_level:
self.file.write(message + '\n')
self.file.flush()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment