Skip to content

Commit

Permalink
Update Python SDK to v4 (xdevplatform#174)
Browse files Browse the repository at this point in the history
* v4 Updates

* removed/updated in v4

* minor typo

* fix flake8 errors

* more flake8 fixes

* finally fixed flake8

* fix under-indented lines
  • Loading branch information
tushdante authored Feb 8, 2019
1 parent 322fc8b commit 3f91354
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 93 deletions.
4 changes: 2 additions & 2 deletions twitter_ads/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (C) 2015 Twitter, Inc.

VERSION = (3, 0, 0)
API_VERSION = '3'
VERSION = (4, 0, 0)
API_VERSION = '4'

from twitter_ads.utils import get_version

Expand Down
11 changes: 4 additions & 7 deletions twitter_ads/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from twitter_ads.resource import resource_property, Resource
from twitter_ads.creative import (AccountMedia, MediaCreative, ScheduledTweet,
Video, VideoWebsiteCard, PromotedTweet)
VideoWebsiteCard, PromotedTweet)
from twitter_ads.audience import TailoredAudience
from twitter_ads.campaign import (AppList, Campaign, FundingInstrument, LineItem,
PromotableUser, ScheduledPromotedTweet)
Expand Down Expand Up @@ -119,12 +119,6 @@ def tailored_audiences(self, id=None, **kwargs):
"""
return self._load_resource(TailoredAudience, id, **kwargs)

def videos(self, id=None, **kwargs):
"""
Returns a collection of videos available to the current account.
"""
return self._load_resource(Video, id, **kwargs)

def account_media(self, id=None, **kwargs):
"""
Returns a collection of account media available to the current account.
Expand Down Expand Up @@ -186,3 +180,6 @@ def scoped_timeline(self, *id, **kwargs):
resource_property(Account, 'timezone_switch_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(Account, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(Account, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(Account, 'account_name')
resource_property(Account, 'industry_type')
76 changes: 24 additions & 52 deletions twitter_ads/audience.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

"""Container for all audience management logic used by the Ads API SDK."""

from twitter_ads.enum import TA_OPERATIONS, TRANSFORM
from twitter_ads.enum import TRANSFORM
from twitter_ads.resource import resource_property, Resource
from twitter_ads.http import TONUpload, Request
from twitter_ads.http import Request
from twitter_ads.error import BadRequest
from twitter_ads.cursor import Cursor
from twitter_ads import API_VERSION
Expand All @@ -15,47 +15,43 @@
class TailoredAudience(Resource):

PROPERTIES = {}

RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences'
RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/{id}'
RESOURCE_UPDATE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audience_changes'
RESOURCE_USERS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/users'
RESOURCE_PERMISSIONS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/permissions'
OPT_OUT = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/global_opt_out'

@classmethod
def create(klass, account, file_path, name, list_type):
def create(klass, account, name):
"""
Uploads and creates a new tailored audience.
Creates a new tailored audience.
"""
upload = TONUpload(account.client, file_path)
audience = klass(account)
getattr(audience, '__create_audience__')(name, list_type)
getattr(audience, '__create_audience__')(name)
try:
getattr(audience, '__update_audience__')(upload.perform(), list_type, TA_OPERATIONS.ADD)
return audience.reload()
except BadRequest as e:
audience.delete()
raise e

@classmethod
def opt_out(klass, account, file_path, list_type):
def users(self, params):
"""
Updates the global opt-out list for the specified advertiser account.
This is a private API and requires whitelisting from Twitter.
This endpoint will allow partners to add, update and remove users from a given
tailored_audience_id.
The endpoint will also accept multiple user identifier types per user as well.
"""
upload = TONUpload(account.client, file_path)
params = {'input_file_path': upload.perform(), 'list_type': list_type}
resource = klass.OPT_OUT.format(account_id=account.id)
Request(account.client, 'put', resource, params=params).perform()
return True

def update(self, file_path, list_type, operation=TA_OPERATIONS.ADD):
"""
Updates the current tailored audience instance.
"""
upload = TONUpload(self.account.client, file_path)
getattr(self, '__update_audience__')(upload.perform(), list_type, operation)
return self.reload()
resource = self.RESOURCE_USERS.format(account_id=self.account.id, id=self.id)
headers = {'Content-Type': 'application/json'}
response = Request(self.account.client,
'post',
resource,
headers=headers,
body=json.dumps(params)).perform()
success_count = response.body['data']['success_count']
total_count = response.body['data']['total_count']
return (success_count, total_count)

def delete(self):
"""
Expand All @@ -65,43 +61,19 @@ def delete(self):
response = Request(self.account.client, 'delete', resource).perform()
return self.from_response(response.body['data'])

def status(self):
"""
Returns the status of all changes for the current tailored audience instance.
"""
if not self.id:
return None

resource = self.RESOURCE_UPDATE.format(account_id=self.account.id)
request = Request(self.account.client, 'get', resource, params=self.to_params())
cursor = list(Cursor(None, request))

return filter(lambda change: change['tailored_audience_id'] == self.id, cursor)

def permissions(self, **kwargs):
"""
Returns a collection of permissions for the curent tailored audience.
"""
self._validate_loaded()
return TailoredAudiencePermission.all(self.account, self.id, **kwargs)

def __create_audience__(self, name, list_type):
params = {'name': name, 'list_type': list_type}
def __create_audience__(self, name):
params = {'name': name}
resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)
response = Request(self.account.client, 'post', resource, params=params).perform()
return self.from_response(response.body['data'])

def __update_audience__(self, location, list_type, operation):
params = {
'tailored_audience_id': self.id,
'input_file_path': location,
'list_type': list_type,
'operation': operation
}

resource = self.RESOURCE_UPDATE.format(account_id=self.account.id)
return Request(self.account.client, 'post', resource, params=params).perform()


# tailored audience properties
# read-only
Expand Down
53 changes: 53 additions & 0 deletions twitter_ads/campaign.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,56 @@ def create(klass, account, **kwargs):
resource = klass.TWEET_CREATE.format(account_id=account.id)
response = Request(account.client, 'post', resource, params=params).perform()
return response.body['data']


class UserSettings(Resource, Persistence):

PROPERTIES = {}

RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/user_settings/{id}'


# user settings properties
# writable
resource_property(UserSettings, 'notification_email')
resource_property(UserSettings, 'contact_phone')
resource_property(UserSettings, 'contact_phone_extension')
resource_property(UserSettings, 'subscribed_email_types')
resource_property(UserSettings, 'user_id')


class TaxSettings(Resource, Persistence):

PROPERTIES = {}

RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tax_settings/{id}'


# tax settings properties
# writable
resource_property(TaxSettings, 'address_city')
resource_property(TaxSettings, 'address_country')
resource_property(TaxSettings, 'address_email')
resource_property(TaxSettings, 'address_first_name')
resource_property(TaxSettings, 'address_last_name')
resource_property(TaxSettings, 'address_name')
resource_property(TaxSettings, 'address_postal_code')
resource_property(TaxSettings, 'address_region')
resource_property(TaxSettings, 'address_street1')
resource_property(TaxSettings, 'address_street2')
resource_property(TaxSettings, 'bill_to')
resource_property(TaxSettings, 'business_relationship')
resource_property(TaxSettings, 'client_address_city')
resource_property(TaxSettings, 'client_address_country')
resource_property(TaxSettings, 'client_address_email')
resource_property(TaxSettings, 'client_address_first_name')
resource_property(TaxSettings, 'client_address_last_name')
resource_property(TaxSettings, 'client_address_name')
resource_property(TaxSettings, 'client_address_postal_code')
resource_property(TaxSettings, 'client_address_region')
resource_property(TaxSettings, 'client_address_street1')
resource_property(TaxSettings, 'client_address_street2')
resource_property(TaxSettings, 'invoice_jurisdiction')
resource_property(TaxSettings, 'tax_category')
resource_property(TaxSettings, 'tax_exemption_id')
resource_property(TaxSettings, 'tax_id')
35 changes: 3 additions & 32 deletions twitter_ads/creative.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,35 +69,6 @@ def save(self):
resource_property(PromotedTweet, 'tweet_id') # SDK limitation


class Video(Resource, Persistence):

PROPERTIES = {}

RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/videos'
RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/videos/{id}'


# video properties
# read-only
resource_property(Video, 'aspect_ratio', readonly=True)
resource_property(Video, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(Video, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Video, 'duration', readonly=True, transform=TRANSFORM.INT)
resource_property(Video, 'id', readonly=True)
resource_property(Video, 'media_key', readonly=True)
resource_property(Video, 'poster_url', readonly=True)
resource_property(Video, 'preview_url', readonly=True)
resource_property(Video, 'ready_to_tweet', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Video, 'reasons_not_servable', readonly=True, transform=TRANSFORM.LIST)
resource_property(Video, 'tweeted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Video, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(Video, 'description')
resource_property(Video, 'poster_image_media_id')
resource_property(Video, 'title')
resource_property(Video, 'video_media_id')


class AccountMedia(Resource, Persistence):

PROPERTIES = {}
Expand Down Expand Up @@ -228,7 +199,7 @@ class ImageAppDownloadCard(Resource, Persistence):
resource_property(ImageAppDownloadCard, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(ImageAppDownloadCard, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
# writable
resource_property(ImageAppDownloadCard, 'app_country_code')
resource_property(ImageAppDownloadCard, 'country_code')
resource_property(ImageAppDownloadCard, 'app_cta')
resource_property(ImageAppDownloadCard, 'iphone_app_id')
resource_property(ImageAppDownloadCard, 'iphone_deep_link')
Expand Down Expand Up @@ -263,7 +234,7 @@ class VideoAppDownloadCard(Resource, Persistence):
resource_property(VideoAppDownloadCard, 'video_poster_url', readonly=True)
resource_property(VideoAppDownloadCard, 'video_url', readonly=True)
# writable
resource_property(VideoAppDownloadCard, 'app_country_code')
resource_property(VideoAppDownloadCard, 'country_code')
resource_property(VideoAppDownloadCard, 'app_cta')
resource_property(VideoAppDownloadCard, 'image_media_id')
resource_property(VideoAppDownloadCard, 'ipad_app_id')
Expand Down Expand Up @@ -521,7 +492,7 @@ def reload(self):

# card properties
# read-only
resource_property(CardsFetch, 'app_country_code', readonly=True)
resource_property(CardsFetch, 'country_code', readonly=True)
resource_property(CardsFetch, 'app_cta', readonly=True)
resource_property(CardsFetch, 'card_type', readonly=True)
resource_property(CardsFetch, 'card_uri', readonly=True)
Expand Down
6 changes: 6 additions & 0 deletions twitter_ads/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,9 @@ def enum(**enums):
HANDLE='TARGETING_CRITERIA',
EVENT='EVENT'
)

LOOKALIKE_EXPANSION = enum(
BROAD='BROAD',
DEFINED='DEFINED',
EXPANDED='EXPANDED'
)

0 comments on commit 3f91354

Please sign in to comment.