Merge branch 'master' of git://github.com/ryanmcgrath/twython
reset the conflicted files that couldn't automerge Conflicts: README.md twython/twython.py
This commit is contained in:
commit
5e63b482eb
8 changed files with 174 additions and 201 deletions
40
AUTHORS.rst
Normal file
40
AUTHORS.rst
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
Special Thanks
|
||||||
|
--------------
|
||||||
|
This is a list of all those who have contributed code to Twython in some way, shape, or form. I think it's
|
||||||
|
exhaustive, but I could be wrong - if you think your name should be here and it's not, please contact
|
||||||
|
me and let me know (or just issue a pull request on GitHub, and leave a note about it so I can just accept it ;).
|
||||||
|
|
||||||
|
Development Lead
|
||||||
|
````````````````
|
||||||
|
|
||||||
|
- Ryan Mcgrath <ryan@venodesigns.net>
|
||||||
|
|
||||||
|
|
||||||
|
Patches and Suggestions
|
||||||
|
````````````````````````
|
||||||
|
|
||||||
|
- `Mike Helmick <https://github.com/michaelhelmick>`_, multiple fixes and proper ``requests`` integration. Too much to list here.
|
||||||
|
- `kracekumar <https://github.com/kracekumar>`_, early ``requests`` work and various fixes.
|
||||||
|
- `Erik Scheffers <https://github.com/eriks5>`_, various fixes regarding OAuth callback URLs.
|
||||||
|
- `Jordan Bouvier <https://github.com/jbouvier>`_, various fixes regarding OAuth callback URLs.
|
||||||
|
- `Dick Brouwer <https://github.com/dikbrouwer>`_, fixes for OAuth Verifier in ``get_authorized_tokens``.
|
||||||
|
- `hades <https://github.com/hades>`_, Fixes to various initial OAuth issues and keeping ``Twython3k`` up-to-date.
|
||||||
|
- `Alex Sutton <https://github.com/alexsdutton/twython/>`_, fix for parameter substitution regular expression (catch underscores!).
|
||||||
|
- `Levgen Pyvovarov <https://github.com/bsn>`_, Various argument fixes, cyrillic text support.
|
||||||
|
- `Mark Liu <https://github.com/mliu7>`_, Missing parameter fix for ``addListMember``.
|
||||||
|
- `Randall Degges <https://github.com/rdegge>`_, PEP-8 fixes, MANIFEST.in, installer fixes.
|
||||||
|
- `Idris Mokhtarzada <https://github.com/idris>`_, Fixes for various example code pieces.
|
||||||
|
- `Jonathan Elsas <https://github.com/jelsas>`_, Fix for original Streaming API stub causing import errors.
|
||||||
|
- `LuqueDaniel <https://github.com/LuqueDaniel>`_, Extended example code where necessary.
|
||||||
|
- `Mesar Hameed <https://github.com/mhameed>`_, Commit to swap ``__getattr__`` trick for a more debuggable solution.
|
||||||
|
- `Remy DeCausemaker <https://github.com/decause>`_, PEP-8 contributions.
|
||||||
|
- `mckellister <https://github.com/mckellister>`_ Twitter Spring 2012 Clean Up fixes to ``Exception`` raised by Twython (Rate Limits, etc).
|
||||||
|
- `Tatz Tsuchiya <http://d.hatena.ne.jp/tatz_tsuchiya/20120115/1326623451>`_, Fix for ``lambda`` scoping in key injection phase.
|
||||||
|
- `Mohammed ALDOUB <https://github.com/Voulnet>`_, Fixes for ``http/https`` access endpoints.
|
||||||
|
- `Fumiaki Kinoshita <https://github.com/fumieval>`_, Re-added Proxy support for 2.3.0.
|
||||||
|
- `Terry Jones <https://github.com/terrycojones>`_, Error cleanup and Exception processing in 2.3.0.
|
||||||
|
- `Leandro Ferreira <https://github.com/leandroferreira>`_, Fix for double-encoding of search queries in 2.3.0.
|
||||||
|
- `Chris Brown <https://github.com/chbrown>`_, Updated to use v1.1 endpoints over v1
|
||||||
|
- `Virendra Rajput <https://github.com/bkvirendra>`_, Fixed unicode (json) encoding in twython.py 2.7.2.
|
||||||
|
- `Paul Solbach <https://github.com/hansenrum>`_, fixed requirement for oauth_verifier
|
||||||
|
- `Greg Nofi <https://github.com/nofeet>`_, fixed using built-in Exception attributes for storing & retrieving error message
|
||||||
49
README.md
49
README.md
|
|
@ -11,7 +11,7 @@ Features
|
||||||
- Twitter lists
|
- Twitter lists
|
||||||
- Timelines
|
- Timelines
|
||||||
- User avatar URL
|
- User avatar URL
|
||||||
- and anything found in [the docs](https://dev.twitter.com/docs/api)
|
- and anything found in [the docs](https://dev.twitter.com/docs/api/1.1)
|
||||||
* Image Uploading!
|
* Image Uploading!
|
||||||
- **Update user status with an image**
|
- **Update user status with an image**
|
||||||
- Change user avatar
|
- Change user avatar
|
||||||
|
|
@ -57,7 +57,7 @@ from twython import Twython
|
||||||
|
|
||||||
'''
|
'''
|
||||||
oauth_token and oauth_token_secret come from the previous step
|
oauth_token and oauth_token_secret come from the previous step
|
||||||
if needed, store those in a session variable or something
|
if needed, store those in a session variable or something. oauth_verifier from the previous call is now required to pass to get_authorized_tokens
|
||||||
'''
|
'''
|
||||||
|
|
||||||
t = Twython(app_key=app_key,
|
t = Twython(app_key=app_key,
|
||||||
|
|
@ -65,7 +65,7 @@ t = Twython(app_key=app_key,
|
||||||
oauth_token=oauth_token,
|
oauth_token=oauth_token,
|
||||||
oauth_token_secret=oauth_token_secret)
|
oauth_token_secret=oauth_token_secret)
|
||||||
|
|
||||||
auth_tokens = t.get_authorized_tokens()
|
auth_tokens = t.get_authorized_tokens(oauth_verifier)
|
||||||
print auth_tokens
|
print auth_tokens
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -90,16 +90,6 @@ t = Twython(app_key=app_key,
|
||||||
print t.getHomeTimeline()
|
print t.getHomeTimeline()
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Get a user avatar url *(no authentication needed)*
|
|
||||||
|
|
||||||
```python
|
|
||||||
from twython import Twython
|
|
||||||
|
|
||||||
t = Twython()
|
|
||||||
print t.getProfileImageUrl('ryanmcgrath', size='bigger')
|
|
||||||
print t.getProfileImageUrl('mikehelmick')
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Streaming API
|
###### Streaming API
|
||||||
*Usage is as follows; it's designed to be open-ended enough that you can adapt it to higher-level (read: Twitter must give you access)
|
*Usage is as follows; it's designed to be open-ended enough that you can adapt it to higher-level (read: Twitter must give you access)
|
||||||
streams.*
|
streams.*
|
||||||
|
|
@ -122,7 +112,7 @@ Twython.stream({
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
As of Twython 2.0.0, we have changed routes for functions to abide by the **[Twitter Spring 2012 clean up](https://dev.twitter.com/docs/deprecations/spring-2012)** Please make changes to your code accordingly.
|
Twython (as of 2.7.0) is currently in the process of ONLY supporting Twitter v1.1 endpoints and deprecating all v1 endpoints! Please see the **[Twitter v1.1 API Documentation](https://dev.twitter.com/docs/api/1.1)** to help migrate your API calls!
|
||||||
|
|
||||||
Development of Twython (specifically, 1.3)
|
Development of Twython (specifically, 1.3)
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
@ -165,34 +155,3 @@ Twython is released under an MIT License - see the LICENSE file for more informa
|
||||||
Want to help?
|
Want to help?
|
||||||
-------------
|
-------------
|
||||||
Twython is useful, but ultimately only as useful as the people using it (say that ten times fast!). If you'd like to help, write example code, contribute patches, document things on the wiki, tweet about it. Your help is always appreciated!
|
Twython is useful, but ultimately only as useful as the people using it (say that ten times fast!). If you'd like to help, write example code, contribute patches, document things on the wiki, tweet about it. Your help is always appreciated!
|
||||||
|
|
||||||
|
|
||||||
Special Thanks to...
|
|
||||||
-----------------------------------------------------------------------------------------------------
|
|
||||||
This is a list of all those who have contributed code to Twython in some way, shape, or form. I think it's
|
|
||||||
exhaustive, but I could be wrong - if you think your name should be here and it's not, please contact
|
|
||||||
me and let me know (or just issue a pull request on GitHub, and leave a note about it so I can just accept it ;)).
|
|
||||||
|
|
||||||
- **[Mike Helmick (michaelhelmick)](https://github.com/michaelhelmick)**, multiple fixes and proper `requests` integration.
|
|
||||||
- **[kracekumar](https://github.com/kracekumar)**, early `requests` work and various fixes.
|
|
||||||
- **[Erik Scheffers (eriks5)](https://github.com/eriks5)**, various fixes regarding OAuth callback URLs.
|
|
||||||
- **[Jordan Bouvier (jbouvier)](https://github.com/jbouvier)**, various fixes regarding OAuth callback URLs.
|
|
||||||
- **[Dick Brouwer (dikbrouwer)](https://github.com/dikbrouwer)**, fixes for OAuth Verifier in `get_authorized_tokens`.
|
|
||||||
- **[hades](https://github.com/hades)**, Fixes to various initial OAuth issues and updates to `Twython3k` to stay current.
|
|
||||||
- **[Alex Sutton (alexdsutton)](https://github.com/alexsdutton/twython/)**, fix for parameter substitution regular expression (catch underscores!).
|
|
||||||
- **[Levgen Pyvovarov (bsn)](https://github.com/bsn)**, Various argument fixes, cyrillic text support.
|
|
||||||
- **[Mark Liu (mliu7)](https://github.com/mliu7)**, Missing parameter fix for `addListMember`.
|
|
||||||
- **[Randall Degges (rdegges)](https://github.com/rdegges)**, PEP-8 fixes, MANIFEST.in, installer fixes.
|
|
||||||
- **[Idris Mokhtarzada (idris)](https://github.com/idris)**, Fixes for various example code pieces.
|
|
||||||
- **[Jonathan Elsas (jelsas)](https://github.com/jelsas)**, Fix for original Streaming API stub causing import errors.
|
|
||||||
- **[LuqueDaniel](https://github.com/LuqueDaniel)**, Extended example code where necessary.
|
|
||||||
- **[Mesar Hameed (mhameed)](https://github.com/mhameed)**, Commit to swap `__getattr__` trick for a more debuggable solution.
|
|
||||||
- **[Remy DeCausemaker (decause)](https://github.com/decause)**, PEP-8 contributions.
|
|
||||||
- **[mckellister](https://github.com/mckellister)**, Fixes to `Exception`s raised by Twython (Rate Limits, etc).
|
|
||||||
- **[tatz_tsuchiya](http://d.hatena.ne.jp/tatz_tsuchiya/20120115/1326623451)**, Fix for `lambda` scoping in key injection phase.
|
|
||||||
- **[Voulnet (Mohammed ALDOUB)](https://github.com/Voulnet)**, Fixes for `http`/`https` access endpoints
|
|
||||||
- **[fumieval](https://github.com/fumieval)**, Re-added Proxy support for 2.3.0.
|
|
||||||
- **[terrycojones](https://github.com/terrycojones)**, Error cleanup and Exception processing in 2.3.0.
|
|
||||||
- **[Leandro Ferreira](https://github.com/leandroferreira)**, Fix for double-encoding of search queries in 2.3.0.
|
|
||||||
- **[Chris Brown](https://github.com/chbrown)**, Updated to use v1.1 endpoints over v1
|
|
||||||
- **[Jonathan Vanasco](https://github.com/jvanasco)**, Debugging support, error_code tracking, Twitter error API tracking, other fixes
|
|
||||||
|
|
|
||||||
48
README.rst
48
README.rst
|
|
@ -10,7 +10,7 @@ Features
|
||||||
- Twitter lists
|
- Twitter lists
|
||||||
- Timelines
|
- Timelines
|
||||||
- User avatar URL
|
- User avatar URL
|
||||||
- and anything found in `the docs <https://dev.twitter.com/docs/api>`_
|
- and anything found in `the docs <https://dev.twitter.com/docs/api/1.1>`_
|
||||||
* Image Uploading!
|
* Image Uploading!
|
||||||
- **Update user status with an image**
|
- **Update user status with an image**
|
||||||
- Change user avatar
|
- Change user avatar
|
||||||
|
|
@ -58,7 +58,7 @@ Handling the callback
|
||||||
|
|
||||||
'''
|
'''
|
||||||
oauth_token and oauth_token_secret come from the previous step
|
oauth_token and oauth_token_secret come from the previous step
|
||||||
if needed, store those in a session variable or something
|
if needed, store those in a session variable or something. oauth_verifier from the previous call is now required to pass to get_authorized_tokens
|
||||||
'''
|
'''
|
||||||
from twython import Twython
|
from twython import Twython
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ Handling the callback
|
||||||
oauth_token=oauth_token,
|
oauth_token=oauth_token,
|
||||||
oauth_token_secret=oauth_token_secret)
|
oauth_token_secret=oauth_token_secret)
|
||||||
|
|
||||||
auth_tokens = t.get_authorized_tokens()
|
auth_tokens = t.get_authorized_tokens(oauth_verifier)
|
||||||
print auth_tokens
|
print auth_tokens
|
||||||
|
|
||||||
*Function definitions (i.e. getHomeTimeline()) can be found by reading over twython/twitter_endpoints.py*
|
*Function definitions (i.e. getHomeTimeline()) can be found by reading over twython/twitter_endpoints.py*
|
||||||
|
|
@ -90,15 +90,6 @@ Getting a user home timeline
|
||||||
# Returns an dict of the user home timeline
|
# Returns an dict of the user home timeline
|
||||||
print t.getHomeTimeline()
|
print t.getHomeTimeline()
|
||||||
|
|
||||||
Get a user avatar url *(no authentication needed)*
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
::
|
|
||||||
|
|
||||||
from twython import Twython
|
|
||||||
|
|
||||||
t = Twython()
|
|
||||||
print t.getProfileImageUrl('ryanmcgrath', size='bigger')
|
|
||||||
print t.getProfileImageUrl('mikehelmick')
|
|
||||||
|
|
||||||
Streaming API
|
Streaming API
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
@ -124,8 +115,7 @@ streams.*
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
* As of Twython 2.0.0, we have changed routes for functions to abide by the `Twitter Spring 2012 clean up <https://dev.twitter.com/docs/deprecations/spring-2012>`_ Please make changes to your code accordingly.
|
* Twython (as of 2.7.0) is currently in the process of ONLY supporting Twitter v1.1 endpoints and deprecating all v1 endpoints! Please see the `Twitter API Documentation <https://dev.twitter.com/docs/api/1.1>`_ to help migrate your API calls!
|
||||||
|
|
||||||
|
|
||||||
Twython && Django
|
Twython && Django
|
||||||
-----------------
|
-----------------
|
||||||
|
|
@ -171,33 +161,3 @@ You can also follow me on Twitter - `@ryanmcgrath <https://twitter.com/ryanmcgra
|
||||||
Want to help?
|
Want to help?
|
||||||
-------------
|
-------------
|
||||||
Twython is useful, but ultimately only as useful as the people using it (say that ten times fast!). If you'd like to help, write example code, contribute patches, document things on the wiki, tweet about it. Your help is always appreciated!
|
Twython is useful, but ultimately only as useful as the people using it (say that ten times fast!). If you'd like to help, write example code, contribute patches, document things on the wiki, tweet about it. Your help is always appreciated!
|
||||||
|
|
||||||
|
|
||||||
Special Thanks to...
|
|
||||||
--------------------
|
|
||||||
This is a list of all those who have contributed code to Twython in some way, shape, or form. I think it's
|
|
||||||
exhaustive, but I could be wrong - if you think your name should be here and it's not, please contact
|
|
||||||
me and let me know (or just issue a pull request on GitHub, and leave a note about it so I can just accept it ;)).
|
|
||||||
|
|
||||||
- `Mike Helmick (michaelhelmick) <https://github.com/michaelhelmick>`_, multiple fixes and proper ``requests`` integration. Too much to list here.
|
|
||||||
- `kracekumar <https://github.com/kracekumar>`_, early ``requests`` work and various fixes.
|
|
||||||
- `Erik Scheffers (eriks5) <https://github.com/eriks5>`_, various fixes regarding OAuth callback URLs.
|
|
||||||
- `Jordan Bouvier (jbouvier) <https://github.com/jbouvier>`_, various fixes regarding OAuth callback URLs.
|
|
||||||
- `Dick Brouwer (dikbrouwer) <https://github.com/dikbrouwer>`_, fixes for OAuth Verifier in ``get_authorized_tokens``.
|
|
||||||
- `hades <https://github.com/hades>`_, Fixes to various initial OAuth issues and updates to ``Twython3k`` to stay current.
|
|
||||||
- `Alex Sutton (alexdsutton) <https://github.com/alexsdutton/twython/>`_, fix for parameter substitution regular expression (catch underscores!).
|
|
||||||
- `Levgen Pyvovarov (bsn) <https://github.com/bsn>`_, Various argument fixes, cyrillic text support.
|
|
||||||
- `Mark Liu (mliu7) <https://github.com/mliu7>`_, Missing parameter fix for ``addListMember``.
|
|
||||||
- `Randall Degges (rdegges) <https://github.com/rdegge>`_, PEP-8 fixes, MANIFEST.in, installer fixes.
|
|
||||||
- `Idris Mokhtarzada (idris) <https://github.com/idris>`_, Fixes for various example code pieces.
|
|
||||||
- `Jonathan Elsas (jelsas) <https://github.com/jelsas>`_, Fix for original Streaming API stub causing import errors.
|
|
||||||
- `LuqueDaniel <https://github.com/LuqueDaniel>`_, Extended example code where necessary.
|
|
||||||
- `Mesar Hameed (mhameed) <https://github.com/mhameed>`_, Commit to swap ``__getattr__`` trick for a more debuggable solution.
|
|
||||||
- `Remy DeCausemaker (decause) <https://github.com/decause>`_, PEP-8 contributions.
|
|
||||||
- `[mckellister](https://github.com/mckellister) <https://dev.twitter.com/docs/deprecations/spring-2012>`_, Fixes to ``Exception`` raised by Twython (Rate Limits, etc).
|
|
||||||
- `tatz_tsuchiya <http://d.hatena.ne.jp/tatz_tsuchiya/20120115/1326623451>`_, Fix for ``lambda`` scoping in key injection phase.
|
|
||||||
- `Voulnet (Mohammed ALDOUB) <https://github.com/Voulnet>`_, Fixes for ``http/https`` access endpoints.
|
|
||||||
- `fumieval <https://github.com/fumieval>`_, Re-added Proxy support for 2.3.0.
|
|
||||||
- `terrycojones <https://github.com/terrycojones>`_, Error cleanup and Exception processing in 2.3.0.
|
|
||||||
- `Leandro Ferreira <https://github.com/leandroferreira>`_, Fix for double-encoding of search queries in 2.3.0.
|
|
||||||
- `Chris Brown <https://github.com/chbrown>`_, Updated to use v1.1 endpoints over v1
|
|
||||||
|
|
|
||||||
4
setup.py
4
setup.py
|
|
@ -2,7 +2,7 @@ from setuptools import setup
|
||||||
from setuptools import find_packages
|
from setuptools import find_packages
|
||||||
|
|
||||||
__author__ = 'Ryan McGrath <ryan@venodesigns.net>'
|
__author__ = 'Ryan McGrath <ryan@venodesigns.net>'
|
||||||
__version__ = '2.6.0'
|
__version__ = '2.7.3'
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
# Basic package information.
|
# Basic package information.
|
||||||
|
|
@ -14,7 +14,7 @@ setup(
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
|
||||||
# Package dependencies.
|
# Package dependencies.
|
||||||
install_requires=['simplejson', 'requests>=1.0.0, <2.0.0', 'requests_oauthlib==0.3.0'],
|
install_requires=['requests>=1.0.0, <2.0.0', 'requests_oauthlib==0.3.0'],
|
||||||
|
|
||||||
# Metadata for PyPI.
|
# Metadata for PyPI.
|
||||||
author='Ryan McGrath',
|
author='Ryan McGrath',
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
from twython import Twython
|
from twython import Twython
|
||||||
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
|
from .exceptions import TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||||
|
|
|
||||||
48
twython/exceptions.py
Normal file
48
twython/exceptions.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
from twitter_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.
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
def __init__(self, msg, error_code=None, retry_after=None):
|
||||||
|
self.error_code = error_code
|
||||||
|
|
||||||
|
if error_code is not None and error_code in twitter_http_status_codes:
|
||||||
|
msg = 'Twitter API returned a %s (%s), %s' % \
|
||||||
|
(error_code,
|
||||||
|
twitter_http_status_codes[error_code][0],
|
||||||
|
msg)
|
||||||
|
|
||||||
|
super(TwythonError, self).__init__(msg)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def msg(self):
|
||||||
|
return self.args[0]
|
||||||
|
|
||||||
|
|
||||||
|
class TwythonAuthError(TwythonError):
|
||||||
|
""" 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.
|
||||||
|
|
||||||
|
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)
|
||||||
|
TwythonError.__init__(self, msg, error_code=error_code)
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
will be replaced with the keyword that gets passed in to the function at call time.
|
will be replaced with the keyword that gets passed in to the function at call time.
|
||||||
|
|
||||||
i.e, in this case, if I pass version = 47 to any function, {{version}} will be replaced
|
i.e, in this case, if I pass version = 47 to any function, {{version}} will be replaced
|
||||||
with 47, instead of defaulting to 1 (said defaulting takes place at conversion time).
|
with 47, instead of defaulting to 1.1 (said defaulting takes place at conversion time).
|
||||||
|
|
||||||
This map is organized the order functions are documented at:
|
This map is organized the order functions are documented at:
|
||||||
https://dev.twitter.com/docs/api/1.1
|
https://dev.twitter.com/docs/api/1.1
|
||||||
|
|
@ -21,7 +21,7 @@ base_url = 'http://api.twitter.com/{{version}}'
|
||||||
api_table = {
|
api_table = {
|
||||||
# Timelines
|
# Timelines
|
||||||
'getMentionsTimeline': {
|
'getMentionsTimeline': {
|
||||||
'url': 'statuses/mentions_timeline',
|
'url': '/statuses/mentions_timeline.json',
|
||||||
'method': 'GET',
|
'method': 'GET',
|
||||||
},
|
},
|
||||||
'getUserTimeline': {
|
'getUserTimeline': {
|
||||||
|
|
@ -87,7 +87,7 @@ api_table = {
|
||||||
'method': 'GET',
|
'method': 'GET',
|
||||||
},
|
},
|
||||||
'destroyDirectMessage': {
|
'destroyDirectMessage': {
|
||||||
'url': '/direct_messages/destroy/{{id}}.json',
|
'url': '/direct_messages/destroy.json',
|
||||||
'method': 'POST',
|
'method': 'POST',
|
||||||
},
|
},
|
||||||
'sendDirectMessage': {
|
'sendDirectMessage': {
|
||||||
|
|
@ -183,11 +183,11 @@ api_table = {
|
||||||
'method': 'GET',
|
'method': 'GET',
|
||||||
},
|
},
|
||||||
'createBlock': {
|
'createBlock': {
|
||||||
'url': '/blocks/create/{{id}}.json',
|
'url': '/blocks/create.json',
|
||||||
'method': 'POST',
|
'method': 'POST',
|
||||||
},
|
},
|
||||||
'destroyBlock': {
|
'destroyBlock': {
|
||||||
'url': '/blocks/destroy/{{id}}.json',
|
'url': '/blocks/destroy.json',
|
||||||
'method': 'POST',
|
'method': 'POST',
|
||||||
},
|
},
|
||||||
'lookupUser': {
|
'lookupUser': {
|
||||||
|
|
@ -215,6 +215,10 @@ api_table = {
|
||||||
'method': 'POST',
|
'method': 'POST',
|
||||||
},
|
},
|
||||||
# See twython.py for update_profile_banner
|
# See twython.py for update_profile_banner
|
||||||
|
'getProfileBannerSizes': {
|
||||||
|
'url': '/users/profile_banner.json',
|
||||||
|
'method': 'GET',
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
# Suggested Users
|
# Suggested Users
|
||||||
|
|
@ -320,6 +324,10 @@ api_table = {
|
||||||
'url': '/lists/members/destroy_all.json',
|
'url': '/lists/members/destroy_all.json',
|
||||||
'method': 'POST'
|
'method': 'POST'
|
||||||
},
|
},
|
||||||
|
'showOwnedLists': {
|
||||||
|
'url': '/lists/ownerships.json',
|
||||||
|
'method': 'GET'
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
# Saved Searches
|
# Saved Searches
|
||||||
|
|
@ -396,8 +404,11 @@ twitter_http_status_codes = {
|
||||||
403: ('Forbidden', 'The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.'),
|
403: ('Forbidden', 'The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.'),
|
||||||
404: ('Not Found', 'The URI requested is invalid or the resource requested, such as a user, does not exists.'),
|
404: ('Not Found', 'The URI requested is invalid or the resource requested, such as a user, does not exists.'),
|
||||||
406: ('Not Acceptable', 'Returned by the Search API when an invalid format is specified in the request.'),
|
406: ('Not Acceptable', 'Returned by the Search API when an invalid format is specified in the request.'),
|
||||||
420: ('Enhance Your Calm', 'Returned by the Search and Trends API when you are being rate limited.'),
|
410: ('Gone', 'This resource is gone. Used to indicate that an API endpoint has been turned off.'),
|
||||||
|
422: ('Unprocessable Entity', 'Returned when an image uploaded to POST account/update_profile_banner is unable to be processed.'),
|
||||||
|
429: ('Too Many Requests', 'Returned in API v1.1 when a request cannot be served due to the application\'s rate limit having been exhausted for the resource.'),
|
||||||
500: ('Internal Server Error', 'Something is broken. Please post to the group so the Twitter team can investigate.'),
|
500: ('Internal Server Error', 'Something is broken. Please post to the group so the Twitter team can investigate.'),
|
||||||
502: ('Bad Gateway', 'Twitter is down or being upgraded.'),
|
502: ('Bad Gateway', 'Twitter is down or being upgraded.'),
|
||||||
503: ('Service Unavailable', 'The Twitter servers are up, but overloaded with requests. Try again later.'),
|
503: ('Service Unavailable', 'The Twitter servers are up, but overloaded with requests. Try again later.'),
|
||||||
|
504: ('Gateway Timeout', 'The Twitter servers are up, but the request couldn\'t be serviced due to some failure within our stack. Try again later.'),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = "Ryan McGrath <ryan@venodesigns.net>"
|
__author__ = "Ryan McGrath <ryan@venodesigns.net>"
|
||||||
__version__ = "2.6.0"
|
__version__ = "2.7.3"
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
import re
|
import re
|
||||||
|
|
@ -23,66 +23,18 @@ except ImportError:
|
||||||
|
|
||||||
# Twython maps keyword based arguments to Twitter API endpoints. The endpoints
|
# Twython maps keyword based arguments to Twitter API endpoints. The endpoints
|
||||||
# table is a file with a dictionary of every API endpoint that Twython supports.
|
# table is a file with a dictionary of every API endpoint that Twython supports.
|
||||||
from twitter_endpoints import base_url, api_table, twitter_http_status_codes
|
from twitter_endpoints import base_url, api_table
|
||||||
|
from .exceptions import TwythonError, TwythonAuthError, TwythonRateLimitError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import simplejson
|
import simplejson as json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
try:
|
import json
|
||||||
# Python 2.6 and up
|
|
||||||
import json as simplejson
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
from django.utils import simplejson
|
|
||||||
except:
|
|
||||||
# Seriously wtf is wrong with you if you get this Exception.
|
|
||||||
raise Exception("Twython requires the simplejson library (or Python 2.6) to work. http://www.undefined.org/python/")
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonError(Exception):
|
|
||||||
"""
|
|
||||||
Generic error class, catch-all for most Twython issues.
|
|
||||||
Special cases are handled by TwythonAPILimit and TwythonAuthError.
|
|
||||||
|
|
||||||
Note: To use these, the 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, TwythonAPILimit, TwythonAuthError
|
|
||||||
"""
|
|
||||||
def __init__(self, msg, error_code=None, retry_after=None):
|
|
||||||
self.msg = msg
|
|
||||||
self.error_code = error_code
|
|
||||||
|
|
||||||
if error_code is not None and error_code in twitter_http_status_codes:
|
|
||||||
self.msg = '%s: %s -- %s' % \
|
|
||||||
(twitter_http_status_codes[error_code][0],
|
|
||||||
twitter_http_status_codes[error_code][1],
|
|
||||||
self.msg)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return repr(self.msg)
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonAuthError(TwythonError):
|
|
||||||
""" 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.
|
|
||||||
retry_wait_seconds is the number of seconds to wait before trying again.
|
|
||||||
"""
|
|
||||||
def __init__(self, msg, error_code, retry_after=None):
|
|
||||||
TwythonError.__init__(self, msg, error_code=error_code)
|
|
||||||
if isinstance(retry_after, int):
|
|
||||||
self.msg = '%s (Retry after %d seconds)' % (msg, retry_after)
|
|
||||||
|
|
||||||
|
|
||||||
class Twython(object):
|
class Twython(object):
|
||||||
def __init__(self, app_key=None, app_secret=None, oauth_token=None, oauth_token_secret=None, \
|
def __init__(self, app_key=None, app_secret=None, oauth_token=None, oauth_token_secret=None,
|
||||||
headers=None, callback_url=None, twitter_token=None, twitter_secret=None, proxies=None, version='1.1' , ssl_verify=True ):
|
headers=None, callback_url=None, twitter_token=None, twitter_secret=None, proxies=None, version='1.1'):
|
||||||
"""Instantiates an instance of Twython. Takes optional parameters for authentication and such (see below).
|
"""Instantiates an instance of Twython. Takes optional parameters for authentication and such (see below).
|
||||||
|
|
||||||
:param app_key: (optional) Your applications key
|
:param app_key: (optional) Your applications key
|
||||||
|
|
@ -92,7 +44,6 @@ class Twython(object):
|
||||||
:param headers: (optional) Custom headers to send along with the request
|
:param headers: (optional) Custom headers to send along with the request
|
||||||
:param callback_url: (optional) If set, will overwrite the callback url set in your application
|
:param callback_url: (optional) If set, will overwrite the callback url set in your application
|
||||||
:param proxies: (optional) A dictionary of proxies, for example {"http":"proxy.example.org:8080", "https":"proxy.example.org:8081"}.
|
:param proxies: (optional) A dictionary of proxies, for example {"http":"proxy.example.org:8080", "https":"proxy.example.org:8081"}.
|
||||||
:param ssl_verify: (optional, default True) Turns off ssl verifiction, for when you have development server issues.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Needed for hitting that there API.
|
# Needed for hitting that there API.
|
||||||
|
|
@ -100,9 +51,7 @@ class Twython(object):
|
||||||
self.api_url = 'https://api.twitter.com/%s'
|
self.api_url = 'https://api.twitter.com/%s'
|
||||||
self.request_token_url = self.api_url % 'oauth/request_token'
|
self.request_token_url = self.api_url % 'oauth/request_token'
|
||||||
self.access_token_url = self.api_url % 'oauth/access_token'
|
self.access_token_url = self.api_url % 'oauth/access_token'
|
||||||
self.authorize_url = self.api_url % 'oauth/authorize'
|
|
||||||
self.authenticate_url = self.api_url % 'oauth/authenticate'
|
self.authenticate_url = self.api_url % 'oauth/authenticate'
|
||||||
self.ssl_verify = ssl_verify
|
|
||||||
|
|
||||||
# Enforce unicode on keys and secrets
|
# Enforce unicode on keys and secrets
|
||||||
self.app_key = app_key and unicode(app_key) or twitter_token and unicode(twitter_token)
|
self.app_key = app_key and unicode(app_key) or twitter_token and unicode(twitter_token)
|
||||||
|
|
@ -197,21 +146,33 @@ class Twython(object):
|
||||||
# why? twitter will return invalid json with an error code in the headers
|
# why? twitter will return invalid json with an error code in the headers
|
||||||
json_error = False
|
json_error = False
|
||||||
try:
|
try:
|
||||||
content = simplejson.loads(content)
|
try:
|
||||||
|
# try to get json
|
||||||
|
content = content.json()
|
||||||
|
except AttributeError:
|
||||||
|
# if unicode detected
|
||||||
|
content = json.loads(content)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
json_error = True
|
json_error = True
|
||||||
content = {}
|
content = {}
|
||||||
|
|
||||||
if response.status_code > 304:
|
if response.status_code > 304:
|
||||||
# If there is no error message, use a default.
|
# If there is no error message, use a default.
|
||||||
error_msg = content.get(
|
errors = content.get('errors',
|
||||||
'error', 'An error occurred processing your request.')
|
[{'message': 'An error occurred processing your request.'}])
|
||||||
self._last_call['api_error'] = error_msg
|
error_message = errors[0]['message']
|
||||||
|
self._last_call['api_error'] = error_message
|
||||||
|
|
||||||
#Twitter API 1.1 , always return 429 when rate limit is exceeded
|
ExceptionType = TwythonError
|
||||||
exceptionType = TwythonRateLimitError if response.status_code == 429 else TwythonError
|
if response.status_code == 429:
|
||||||
|
# Twitter API 1.1, always return 429 when rate limit is exceeded
|
||||||
|
ExceptionType = TwythonRateLimitError
|
||||||
|
elif response.status_code == 401 or 'Bad Authentication data' in error_message:
|
||||||
|
# Twitter API 1.1, returns a 401 Unauthorized or
|
||||||
|
# a 400 "Bad Authentication data" for invalid/expired app keys/user tokens
|
||||||
|
ExceptionType = TwythonAuthError
|
||||||
|
|
||||||
raise exceptionType(error_msg,
|
raise ExceptionType(error_message,
|
||||||
error_code=response.status_code,
|
error_code=response.status_code,
|
||||||
retry_after=response.headers.get('retry-after'))
|
retry_after=response.headers.get('retry-after'))
|
||||||
|
|
||||||
|
|
@ -256,10 +217,10 @@ class Twython(object):
|
||||||
This will return None if the header is not present
|
This will return None if the header is not present
|
||||||
|
|
||||||
Most useful for the following header information:
|
Most useful for the following header information:
|
||||||
x-ratelimit-limit
|
x-rate-limit-limit
|
||||||
x-ratelimit-remaining
|
x-rate-limit-remaining
|
||||||
x-ratelimit-class
|
x-rate-limit-class
|
||||||
x-ratelimit-reset
|
x-rate-limit-reset
|
||||||
"""
|
"""
|
||||||
if self._last_call is None:
|
if self._last_call is None:
|
||||||
raise TwythonError('This function must be called after an API call. It delivers header information.')
|
raise TwythonError('This function must be called after an API call. It delivers header information.')
|
||||||
|
|
@ -267,17 +228,21 @@ class Twython(object):
|
||||||
return self._last_call['headers'][header]
|
return self._last_call['headers'][header]
|
||||||
return self._last_call
|
return self._last_call
|
||||||
|
|
||||||
def get_authentication_tokens(self):
|
def get_authentication_tokens(self, force_login=False, screen_name=''):
|
||||||
"""Returns an authorization URL for a user to hit.
|
"""Returns an authorization URL for a user to hit.
|
||||||
|
|
||||||
|
:param force_login: (optional) Forces the user to enter their credentials to ensure the correct users account is authorized.
|
||||||
|
:param app_secret: (optional) If forced_login is set OR user is not currently logged in, Prefills the username input box of the OAuth login screen with the given value
|
||||||
"""
|
"""
|
||||||
request_args = {}
|
request_args = {}
|
||||||
if self.callback_url:
|
if self.callback_url:
|
||||||
request_args['oauth_callback'] = self.callback_url
|
request_args['oauth_callback'] = self.callback_url
|
||||||
|
|
||||||
response = self.client.get(self.request_token_url, params=request_args, verify=self.ssl_verify)
|
response = self.client.get(self.request_token_url, params=request_args)
|
||||||
|
if response.status_code == 401:
|
||||||
if response.status_code != 200:
|
raise TwythonAuthError(response.content, error_code=response.status_code)
|
||||||
raise TwythonAuthError("Seems something couldn't be verified with your OAuth junk. Error: %s, Message: %s" % (response.status_code, response.content))
|
elif response.status_code != 200:
|
||||||
|
raise TwythonError(response.content, error_code=response.status_code)
|
||||||
|
|
||||||
request_tokens = dict(parse_qsl(response.content))
|
request_tokens = dict(parse_qsl(response.content))
|
||||||
if not request_tokens:
|
if not request_tokens:
|
||||||
|
|
@ -289,6 +254,12 @@ class Twython(object):
|
||||||
'oauth_token': request_tokens['oauth_token'],
|
'oauth_token': request_tokens['oauth_token'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if force_login:
|
||||||
|
auth_url_params.update({
|
||||||
|
'force_login': force_login,
|
||||||
|
'screen_name': screen_name
|
||||||
|
})
|
||||||
|
|
||||||
# Use old-style callback argument if server didn't accept new-style
|
# Use old-style callback argument if server didn't accept new-style
|
||||||
if self.callback_url and not oauth_callback_confirmed:
|
if self.callback_url and not oauth_callback_confirmed:
|
||||||
auth_url_params['oauth_callback'] = self.callback_url
|
auth_url_params['oauth_callback'] = self.callback_url
|
||||||
|
|
@ -297,10 +268,10 @@ class Twython(object):
|
||||||
|
|
||||||
return request_tokens
|
return request_tokens
|
||||||
|
|
||||||
def get_authorized_tokens(self):
|
def get_authorized_tokens(self, oauth_verifier):
|
||||||
"""Returns authorized tokens after they go through the auth_url phase.
|
"""Returns authorized tokens after they go through the auth_url phase.
|
||||||
"""
|
"""
|
||||||
response = self.client.get(self.access_token_url, verify=self.ssl_verify)
|
response = self.client.get(self.access_token_url, params={'oauth_verifier': oauth_verifier})
|
||||||
authorized_tokens = dict(parse_qsl(response.content))
|
authorized_tokens = dict(parse_qsl(response.content))
|
||||||
if not authorized_tokens:
|
if not authorized_tokens:
|
||||||
raise TwythonError('Unable to decode authorized tokens.')
|
raise TwythonError('Unable to decode authorized tokens.')
|
||||||
|
|
@ -431,13 +402,13 @@ class Twython(object):
|
||||||
**params - You may pass items that are taken in this doc
|
**params - You may pass items that are taken in this doc
|
||||||
(https://dev.twitter.com/docs/api/1.1/post/statuses/update_with_media)
|
(https://dev.twitter.com/docs/api/1.1/post/statuses/update_with_media)
|
||||||
"""
|
"""
|
||||||
subdomain = 'upload' if version == '1' else 'api'
|
|
||||||
url = 'https://%s.twitter.com/%s/statuses/update_with_media.json' % (subdomain, version)
|
url = 'https://api.twitter.com/%s/statuses/update_with_media.json' % version
|
||||||
return self._media_update(url,
|
return self._media_update(url,
|
||||||
{'media': (file_, open(file_, 'rb'))},
|
{'media': (file_, open(file_, 'rb'))},
|
||||||
**params)
|
**params)
|
||||||
|
|
||||||
def updateProfileBannerImage(self, file_, version=1, **params):
|
def updateProfileBannerImage(self, file_, version='1.1', **params):
|
||||||
"""Updates the users profile banner
|
"""Updates the users profile banner
|
||||||
|
|
||||||
:param file_: (required) A string to the location of the file
|
:param file_: (required) A string to the location of the file
|
||||||
|
|
@ -447,7 +418,7 @@ class Twython(object):
|
||||||
**params - You may pass items that are taken in this doc
|
**params - You may pass items that are taken in this doc
|
||||||
(https://dev.twitter.com/docs/api/1/post/account/update_profile_banner)
|
(https://dev.twitter.com/docs/api/1/post/account/update_profile_banner)
|
||||||
"""
|
"""
|
||||||
url = 'https://api.twitter.com/%d/account/update_profile_banner.json' % version
|
url = 'https://api.twitter.com/%s/account/update_profile_banner.json' % version
|
||||||
return self._media_update(url,
|
return self._media_update(url,
|
||||||
{'banner': (file_, open(file_, 'rb'))},
|
{'banner': (file_, open(file_, 'rb'))},
|
||||||
**params)
|
**params)
|
||||||
|
|
@ -455,28 +426,12 @@ class Twython(object):
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
def getProfileImageUrl(self, username, size='normal', version='1'):
|
def getProfileImageUrl(self, username, size='normal', version='1'):
|
||||||
"""Gets the URL for the user's profile image.
|
warnings.warn(
|
||||||
|
"This function has been deprecated. Twitter API v1.1 will not have a dedicated endpoint \
|
||||||
:param username: (required) Username, self explanatory.
|
for this functionality.",
|
||||||
:param size: (optional) Default 'normal' (48px by 48px)
|
DeprecationWarning,
|
||||||
bigger - 73px by 73px
|
stacklevel=2
|
||||||
mini - 24px by 24px
|
)
|
||||||
original - undefined, be careful -- images may be
|
|
||||||
large in bytes and/or size.
|
|
||||||
:param version: (optional) A number, default 1 because that's the
|
|
||||||
only API version for Twitter that supports this call
|
|
||||||
"""
|
|
||||||
endpoint = 'users/profile_image/%s' % username
|
|
||||||
url = self.api_url % version + '/' + endpoint
|
|
||||||
|
|
||||||
response = self.client.get(url, params={'size': size}, allow_redirects=False, verify=self.ssl_verify)
|
|
||||||
image_url = response.headers.get('location')
|
|
||||||
|
|
||||||
if response.status_code in (301, 302, 303, 307) and image_url is not None:
|
|
||||||
return image_url
|
|
||||||
else:
|
|
||||||
raise TwythonError('getProfileImageUrl() threw an error.',
|
|
||||||
error_code=response.status_code)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def stream(data, callback):
|
def stream(data, callback):
|
||||||
|
|
@ -528,7 +483,7 @@ class Twython(object):
|
||||||
for line in stream.iter_lines():
|
for line in stream.iter_lines():
|
||||||
if line:
|
if line:
|
||||||
try:
|
try:
|
||||||
callback(simplejson.loads(line))
|
callback(json.loads(line))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise TwythonError('Response was not valid JSON, unable to decode.')
|
raise TwythonError('Response was not valid JSON, unable to decode.')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue