Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #414 from bear/develop
Browse files Browse the repository at this point in the history
merge 3.2 Develop branch to prepare for release
  • Loading branch information
bear authored Nov 24, 2016
2 parents 5c5ddbd + 6a3bc3d commit 1414e12
Show file tree
Hide file tree
Showing 29 changed files with 751 additions and 568 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ docs:
$(MAKE) -C doc html

lint:
flake8 twitter > violations.flake8.txt
pycodestyle --config={toxinidir}/setup.cfg twitter tests

test: lint
python setup.py test
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ You can install python-twitter using::

$ pip install python-twitter


If you are using python-twitter on Google App Engine, see `more information <GAE.rst>`_ about including 3rd party vendor library dependencies in your App Engine project.


Expand Down
4 changes: 4 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ What's New

* Google App Engine support has been reintegrated into the library. Check out `PR #383 <https://github.com/bear/python-twitter/pull/383>`_.

* `video_info` is now available on a `twitter.models.Media` object, which allows access to video urls/bitrates/etc. in the `extended_entities` node of a tweet.

What's Changed
--------------

Expand Down Expand Up @@ -99,3 +101,5 @@ ______________
* Updated examples, specifically ``examples/twitter-to-xhtml.py``, ``examples/view_friends.py``, ``examples/shorten_url.py``

* Updated ``get_access_token.py`` script to be python3 compatible.

* :py:func:`twitter.api.Api.GetStreamFilter()` now accepts an optional languages parameter as a list.
79 changes: 79 additions & 0 deletions doc/changes_to_tweet_counting.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
REST API Changes
=================

Information compiled on Sept 14, 2016.

``statuses/update`` Endpoint
----------------------------

``auto_populate_reply_metadata``
+++++++++++++++++++++++++++++++

* Default is ``false``

* Must have ``in_reply_to_status_id`` set.

* Unknown what happens if not set. Probably error (does it get posted?)

* If the status to which you're replying is deleted, tweet will fail to post.

``exclude_reply_user_ids``
++++++++++++++++++++++++++

* List of ``user_ids`` to remove from result of ``auto_populate_reply_metadata``.

* Doesn't apply to the first ``user_id``.

* If you try to remove it, this will be silently ignored by Twitter.

``attachment_url``
++++++++++++++++++

* Must be a status permalnk or a DM deep link.

* If it's anything else and included in this parameter, Twitter will return an error.


Most Other Endpoints
--------------------

``tweet_mode``
++++++++++++++

* Any endpoint that returns a tweet will accept this param.

* Must be in ``['compat', 'extended']``

* If ``tweet_mode == 'compat'``, then no ``extended_tweet`` node in the json returned.

* If ``tweet_mode == 'extended'``, then you'll get the ``extended_tweet`` node.


Errors
------
* 44 -> URL passed to attachment_url is invalid

* 385 -> Replied to deleted tweet or tweet not visible to you

* 386 -> Too many attachments types (ie a GIF + quote tweet)


Streaming API
=============

Everything is going to be compatibility mode for now; however **all** tweets with have an ``extended_tweet`` node, which will contain the new information. According to Twitter's documentation though, there's the possibility that this node may not exist. We should be careful about making assumptions here.


Changes to Models
=================

Classic tweet: tweet with length < 140 char.
Extended tweet: tweet with extended entities and text > 140 chars.

Twitter doesn't say if extended tweet with a total length of < 140 characters will be considered a "Classic tweet". They also state that an extended tweet shall have "text content [that] exceeds 140 characters in length", however this is contradictory to earlier statements about total text length retaining a hard max at 140 characters.

There will be two rendering modes: Compatibility and Extended. If in compatibility mode and tweet is "classic", no changes to tweet JSON. If in Extended mode, the following will change:

* ``text`` -> truncated version of the extended tweet's text + "..." + permalink to tweet. (Twitter is mute on whether an extended tweet's with (text + @mentions + urls) < 140 characters will have the @mentions + urls put back in ``text`` field.)

* ``truncated`` -> gets set to ``True`` if extended tweet is rendered in compat mode.
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@
# built documents.
#
# The short X.Y version.
version = '3.1'
version = '3.2'
# The full version, including alpha/beta/rc tags.
release = '3.1'
release = '3.2dev0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
12 changes: 8 additions & 4 deletions examples/streaming/track_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

# ----------------------------------------------------------------------

# This file demonstrates how to track mentions of a specific set of users and
# archive those mentions to a local file. The output file will contain one
# JSON string per line per Tweet.
# This file demonstrates how to track mentions of a specific set of users in
# english language and archive those mentions to a local file. The output
# file will contain one JSON string per line per Tweet.

# To use this example, replace the W/X/Y/Zs with your keys obtained from
# Twitter, or uncomment the lines for getting an environment variable. If you
Expand Down Expand Up @@ -52,6 +52,10 @@
'@twitterapi',
'@support']

# Languages to filter tweets by is a list. This will be joined by Twitter
# to return data mentioning tweets only in the english language.
LANGUAGES = ['en']

# Since we're going to be using a streaming endpoint, there is no need to worry
# about rate limits.
api = Api(CONSUMER_KEY,
Expand All @@ -64,7 +68,7 @@ def main():
with open('output.txt', 'a') as f:
# api.GetStreamFilter will return a generator that yields one status
# message (i.e., Tweet) at a time as a JSON dictionary.
for line in api.GetStreamFilter(track=USERS):
for line in api.GetStreamFilter(track=USERS, languages=LANGUAGES):
f.write(json.dumps(line))
f.write('\n')

Expand Down
8 changes: 4 additions & 4 deletions examples/view_friends.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@


# Create an Api instance.
api = twitter.Api(consumer_key='consumer_key',
consumer_secret='consumer_secret',
access_token_key='access_token',
access_token_secret='access_token_secret')
api = twitter.Api(consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET,
access_token_key=ACCESS_TOKEN,
access_token_secret=ACCESS_TOKEN_SECRET)

users = api.GetFriends()

Expand Down
1 change: 0 additions & 1 deletion requirements.testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pytest
pytest-cov
pytest-runner
mccabe
flake8
mock
six
coverage
Expand Down
6 changes: 3 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ ignore =
violations.flake8.txt

[flake8]
ignore = E111,E124,E126,E201,E202,E221,E241,E302,E501
ignore = E111,E124,E126,E221,E501

[pep8]
ignore = E111,E124,E126,E128,E201,E202,E221,E226,E241,E301,E302,E303,E402,E501,W291
max-line-length = 160
ignore = E111,E124,E126,E221,E501
max-line-length = 100
1 change: 1 addition & 0 deletions testdata/3.2/extended_tweet_in_compat_mode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"contributors": null, "in_reply_to_status_id_str": null, "lang": "en", "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "in_reply_to_user_id": null, "possibly_sensitive_appealable": false, "coordinates": null, "truncated": true, "retweet_count": 0, "retweeted": false, "possibly_sensitive": false, "in_reply_to_user_id_str": null, "entities": {"symbols": [], "user_mentions": [], "urls": [{"expanded_url": "https://twitter.com/i/web/status/782737772490600448", "indices": [117, 140], "url": "https://t.co/et3OTOxWSa", "display_url": "twitter.com/i/web/status/7\u2026"}], "hashtags": []}, "geo": null, "is_quote_status": false, "favorite_count": 0, "id_str": "782737772490600448", "id": 782737772490600448, "created_at": "Mon Oct 03 00:23:22 +0000 2016", "text": "has more details about these changes. Thanks for making more expressive!writing requirements to python_twitt pytho\u2026 https://t.co/et3OTOxWSa", "place": null, "in_reply_to_screen_name": null, "in_reply_to_status_id": null, "favorited": false, "user": {"follow_request_sent": false, "protected": true, "default_profile_image": true, "profile_sidebar_fill_color": "000000", "favourites_count": 1, "utc_offset": null, "has_extended_profile": false, "lang": "en", "profile_image_url": "http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png", "friends_count": 2, "profile_text_color": "000000", "geo_enabled": true, "profile_banner_url": "https://pbs.twimg.com/profile_banners/4012966701/1453123196", "verified": false, "listed_count": 1, "is_translator": false, "location": "", "entities": {"description": {"urls": []}}, "name": "notinourselves", "is_translation_enabled": false, "time_zone": null, "id_str": "4012966701", "profile_background_tile": false, "followers_count": 1, "profile_sidebar_border_color": "000000", "contributors_enabled": false, "following": false, "description": "", "url": null, "statuses_count": 84, "default_profile": false, "profile_link_color": "000000", "profile_image_url_https": "https://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png", "notifications": false, "profile_background_image_url": "http://pbs.twimg.com/profile_background_images/736320724164448256/LgaAQoav.jpg", "screen_name": "notinourselves", "profile_background_image_url_https": "https://pbs.twimg.com/profile_background_images/736320724164448256/LgaAQoav.jpg", "id": 4012966701, "profile_use_background_image": true, "created_at": "Wed Oct 21 23:53:04 +0000 2015", "profile_background_color": "000000"}}
1 change: 1 addition & 0 deletions testdata/3.2/extended_tweet_in_extended_mode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"contributors": null, "in_reply_to_status_id_str": null, "lang": "en", "in_reply_to_user_id_str": null, "in_reply_to_user_id": null, "possibly_sensitive_appealable": false, "coordinates": null, "full_text": "has more details about these changes. Thanks for making more expressive!writing requirements to python_twitt python_twitter.egg-info/SOURCE https://t.co/JWSPztfoyt", "truncated": false, "retweet_count": 0, "retweeted": false, "possibly_sensitive": false, "entities": {"symbols": [], "media": [{"id_str": "782737766455119872", "type": "photo", "media_url_https": "https://pbs.twimg.com/media/CtzX2fnXEAAMAjK.jpg", "display_url": "pic.twitter.com/JWSPztfoyt", "sizes": {"large": {"w": 1024, "resize": "fit", "h": 1024}, "thumb": {"w": 150, "resize": "crop", "h": 150}, "small": {"w": 680, "resize": "fit", "h": 680}, "medium": {"w": 1024, "resize": "fit", "h": 1024}}, "expanded_url": "https://twitter.com/notinourselves/status/782737772490600448/photo/1", "indices": [141, 164], "id": 782737766455119872, "url": "https://t.co/JWSPztfoyt", "media_url": "http://pbs.twimg.com/media/CtzX2fnXEAAMAjK.jpg"}], "user_mentions": [], "urls": [], "hashtags": []}, "geo": null, "is_quote_status": false, "favorite_count": 0, "id_str": "782737772490600448", "extended_entities": {"media": [{"id_str": "782737766455119872", "type": "photo", "media_url_https": "https://pbs.twimg.com/media/CtzX2fnXEAAMAjK.jpg", "display_url": "pic.twitter.com/JWSPztfoyt", "sizes": {"large": {"w": 1024, "resize": "fit", "h": 1024}, "thumb": {"w": 150, "resize": "crop", "h": 150}, "small": {"w": 680, "resize": "fit", "h": 680}, "medium": {"w": 1024, "resize": "fit", "h": 1024}}, "expanded_url": "https://twitter.com/notinourselves/status/782737772490600448/photo/1", "indices": [141, 164], "id": 782737766455119872, "url": "https://t.co/JWSPztfoyt", "media_url": "http://pbs.twimg.com/media/CtzX2fnXEAAMAjK.jpg", "ext_alt_text": null}]}, "created_at": "Mon Oct 03 00:23:22 +0000 2016", "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "place": null, "favorited": false, "in_reply_to_screen_name": null, "in_reply_to_status_id": null, "id": 782737772490600448, "display_text_range": [0, 140], "user": {"follow_request_sent": false, "protected": true, "default_profile_image": true, "profile_sidebar_fill_color": "000000", "favourites_count": 1, "utc_offset": null, "has_extended_profile": false, "lang": "en", "profile_image_url": "http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png", "friends_count": 2, "profile_text_color": "000000", "geo_enabled": true, "profile_banner_url": "https://pbs.twimg.com/profile_banners/4012966701/1453123196", "verified": false, "listed_count": 1, "is_translator": false, "location": "", "entities": {"description": {"urls": []}}, "name": "notinourselves", "is_translation_enabled": false, "time_zone": null, "id_str": "4012966701", "profile_background_tile": false, "followers_count": 1, "profile_sidebar_border_color": "000000", "contributors_enabled": false, "following": false, "description": "", "url": null, "statuses_count": 84, "default_profile": false, "profile_link_color": "000000", "profile_image_url_https": "https://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png", "notifications": false, "profile_background_image_url": "http://pbs.twimg.com/profile_background_images/736320724164448256/LgaAQoav.jpg", "screen_name": "notinourselves", "profile_background_image_url_https": "https://pbs.twimg.com/profile_background_images/736320724164448256/LgaAQoav.jpg", "id": 4012966701, "profile_use_background_image": true, "created_at": "Wed Oct 21 23:53:04 +0000 2015", "profile_background_color": "000000"}}
1 change: 1 addition & 0 deletions testdata/get_status_promoted_video_tweet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"possibly_sensitive_appealable": false, "entities": {"user_mentions": [], "hashtags": [{"indices": [22, 29], "text": "amiibo"}, {"indices": [33, 41], "text": "Picross"}], "symbols": [], "urls": [{"display_url": "nintendo.com/games/detail/p\u2026", "url": "https://t.co/MjciohRcuW", "expanded_url": "http://www.nintendo.com/games/detail/picross-3d-round-2-3ds", "indices": [90, 113]}], "media": [{"type": "photo", "id": 778025997606105089, "url": "https://t.co/ibou4buFxe", "media_url": "http://pbs.twimg.com/media/CswaoY4UAAA8-Zj.jpg", "indices": [114, 137], "id_str": "778025997606105089", "display_url": "pic.twitter.com/ibou4buFxe", "expanded_url": "https://twitter.com/NintendoAmerica/status/778307811012780032/video/1", "sizes": {"large": {"resize": "fit", "w": 1280, "h": 720}, "small": {"resize": "fit", "w": 680, "h": 383}, "thumb": {"resize": "crop", "w": 150, "h": 150}, "medium": {"resize": "fit", "w": 1200, "h": 675}}, "media_url_https": "https://pbs.twimg.com/media/CswaoY4UAAA8-Zj.jpg"}]}, "extended_entities": {"media": [{"id": 778025997606105089, "url": "https://t.co/ibou4buFxe", "media_url": "http://pbs.twimg.com/media/CswaoY4UAAA8-Zj.jpg", "video_info": {"duration_millis": 62996, "aspect_ratio": [16, 9], "variants": [{"bitrate": 320000, "url": "https://video.twimg.com/amplify_video/778025997606105089/vid/320x180/5Qr0z_HeycC2DvRj.mp4", "content_type": "video/mp4"}, {"bitrate": 2176000, "url": "https://video.twimg.com/amplify_video/778025997606105089/vid/1280x720/mUiy98wFwECTRNxT.mp4", "content_type": "video/mp4"}, {"bitrate": 832000, "url": "https://video.twimg.com/amplify_video/778025997606105089/vid/640x360/SX_HepRw0MeH796L.mp4", "content_type": "video/mp4"}, {"url": "https://video.twimg.com/amplify_video/778025997606105089/pl/PX7Gx8TRhJyUZ2-L.m3u8", "content_type": "application/x-mpegURL"}, {"url": "https://video.twimg.com/amplify_video/778025997606105089/pl/PX7Gx8TRhJyUZ2-L.mpd", "content_type": "application/dash+xml"}]}, "ext_alt_text": null, "sizes": {"large": {"resize": "fit", "w": 1280, "h": 720}, "small": {"resize": "fit", "w": 680, "h": 383}, "thumb": {"resize": "crop", "w": 150, "h": 150}, "medium": {"resize": "fit", "w": 1200, "h": 675}}, "indices": [114, 137], "type": "video", "additional_media_info": {"title": "Picross 3D Round 2 - amiibo \"Hands-On\u201d Gameplay ", "description": "Unlock more puzzles in Picross 3D Round 2 with amiibo!", "call_to_actions": {"visit_site": {"url": "http://www.nintendo.com/games/detail/picross-3d-round-2-3ds"}}, "monetizable": false, "embeddable": true}, "id_str": "778025997606105089", "display_url": "pic.twitter.com/ibou4buFxe", "expanded_url": "https://twitter.com/NintendoAmerica/status/778307811012780032/video/1", "media_url_https": "https://pbs.twimg.com/media/CswaoY4UAAA8-Zj.jpg"}]}, "favorited": false, "text": "Puzzled on how to use #amiibo in #Picross 3D Round 2? Just follow these six simple steps!\nhttps://t.co/MjciohRcuW https://t.co/ibou4buFxe", "retweeted": false, "retweet_count": 119, "user": {"is_translator": false, "profile_image_url_https": "https://pbs.twimg.com/profile_images/745752686780387333/wsjpSx2K_normal.jpg", "url": "https://t.co/cMLmFbyXaL", "entities": {"description": {"urls": [{"display_url": "esrb.org", "url": "https://t.co/OgSR65P8OY", "expanded_url": "http://esrb.org", "indices": [103, 126]}]}, "url": {"urls": [{"display_url": "nintendo.com", "url": "https://t.co/cMLmFbyXaL", "expanded_url": "http://www.nintendo.com/", "indices": [0, 23]}]}}, "listed_count": 10347, "friends_count": 1350, "profile_background_image_url_https": "https://pbs.twimg.com/profile_background_images/623621309210083328/e9ZICp8d.jpg", "profile_background_image_url": "http://pbs.twimg.com/profile_background_images/623621309210083328/e9ZICp8d.jpg", "profile_use_background_image": true, "profile_link_color": "038543", "description": "Welcome to the official Nintendo profile for gaming news! We\u2019re listening, too. For ESRB ratings go to https://t.co/OgSR65P8OY", "favourites_count": 260, "protected": false, "profile_background_tile": false, "id_str": "5162861", "has_extended_profile": false, "profile_text_color": "333333", "verified": true, "follow_request_sent": false, "contributors_enabled": false, "lang": "en", "id": 5162861, "statuses_count": 11909, "notifications": false, "location": "", "created_at": "Wed Apr 18 22:43:15 +0000 2007", "name": "Nintendo of America", "is_translation_enabled": false, "default_profile_image": false, "profile_background_color": "ACDED6", "utc_offset": -25200, "geo_enabled": false, "profile_banner_url": "https://pbs.twimg.com/profile_banners/5162861/1476972565", "profile_sidebar_border_color": "FFFFFF", "screen_name": "NintendoAmerica", "profile_sidebar_fill_color": "F6F6F6", "profile_image_url": "http://pbs.twimg.com/profile_images/745752686780387333/wsjpSx2K_normal.jpg", "default_profile": false, "time_zone": "Pacific Time (US & Canada)", "followers_count": 5246308, "translator_type": "none", "following": false}, "id_str": "778307811012780032", "is_quote_status": false, "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "contributors": null, "id": 778307811012780032, "favorite_count": 609, "in_reply_to_screen_name": null, "geo": null, "created_at": "Tue Sep 20 19:00:17 +0000 2016", "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "truncated": false, "lang": "en", "in_reply_to_user_id_str": null, "place": null, "coordinates": null, "in_reply_to_user_id": null, "possibly_sensitive": false}
1 change: 1 addition & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ACCESS_TOKEN_KEY = os.getenv('ACCESS_TOKEN_KEY', None)
ACCESS_TOKEN_SECRET = os.getenv('ACCESS_TOKEN_SECRET', None)


@unittest.skipIf(not CONSUMER_KEY and not CONSUMER_SECRET, "No tokens provided")
class ApiTest(unittest.TestCase):
def setUp(self):
Expand Down
Loading

0 comments on commit 1414e12

Please sign in to comment.