def test_analytics_async(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.POST, with_resource('/' + API_VERSION + '/stats/jobs/accounts/2iqph'), body=with_fixture('analytics_async_post'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/stats/jobs/accounts/2iqph'), body=with_fixture('analytics_async_get'), content_type='application/json') client = Client( characters(40), characters(40), characters(40), characters(40) ) account = Account.load(client, '2iqph') ids = ['aaaa'] metric_groups = [METRIC_GROUP.ENGAGEMENT] stats = Campaign.queue_async_stats_job( account, ids, metric_groups, granularity=GRANULARITY.TOTAL ) # test POST request response - queue_async_stats_job() assert 'granularity=TOTAL' in responses.calls[1].request.url assert stats is not None assert isinstance(stats, dict) assert stats['entity_ids'] == ids # call async_stats_job_result() through Campaign class (inheritance) job_id = stats['id_str'] job_result = Campaign.async_stats_job_result( account, [job_id]).first assert job_result is not None assert isinstance(job_result, dict) assert job_result['url'] == 'https://ton.twimg.com/advertiser-api-async-analytics/stats.json.gz' # call async_stats_job_result() from Analytics class directly job_result = Analytics.async_stats_job_result( account, [job_id]).first assert job_result is not None assert isinstance(job_result, dict) assert job_result['url'] == 'https://ton.twimg.com/advertiser-api-async-analytics/stats.json.gz'
def new(request): """ Returns a new campaign """ client = Client(settings.SOCIAL_AUTH_TWITTER_KEY, settings.SOCIAL_AUTH_TWITTER_SECRET, settings.TWITTER_ACCESS_TOKEN, settings.TWITTER_ACCESS_TOKEN_SECRET) account_id = request.GET.get("account_id", "") campaign_name = request.GET.get("campaign", "") daily_budget = request.GET.get("daily_budget", "") account = client.accounts(account_id) # create your campaign json_data = {} try: campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next( ).id campaign.daily_budget_amount_local_micro = int(daily_budget) * 1000 campaign.name = campaign_name campaign.paused = True campaign.start_time = datetime.datetime.utcnow() campaign.save() json_data = { "valid": True, "account_id": account_id, "campaign_name": campaign_name, "campaign_id": campaign.id } except Error as e: json_data["response"] = e.details json_data["valid"] = False # passing as we send the json_data pass return HttpResponse(json.dumps(json_data), content_type="application/json")
def new(request): """ Returns a new campaign """ client = Client( settings.SOCIAL_AUTH_TWITTER_KEY, settings.SOCIAL_AUTH_TWITTER_SECRET, settings.TWITTER_ACCESS_TOKEN, settings.TWITTER_ACCESS_TOKEN_SECRET) account_id = request.GET.get("account_id", "") campaign_name = request.GET.get("campaign", "") daily_budget = request.GET.get("daily_budget", "") account = client.accounts(account_id) # create your campaign json_data = {} try: campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next().id campaign.daily_budget_amount_local_micro = int(daily_budget) * 1000 campaign.name = campaign_name campaign.paused = True campaign.start_time = datetime.datetime.utcnow() campaign.save() json_data = { "valid": True, "account_id": account_id, "campaign_name": campaign_name, "campaign_id": campaign.id} except Error as e: json_data["response"] = e.details json_data["valid"] = False # passing as we send the json_data pass return HttpResponse(json.dumps(json_data), content_type="application/json")
def test_analytics_sync_stats(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/stats/accounts/2iqph'), body=with_fixture('analytics_sync_stats'), content_type='application/json') client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') ids = ['aaaa', 'bbbb'] metric_groups = [METRIC_GROUP.ENGAGEMENT] stats = Campaign.all_stats(account, ids, metric_groups, granularity=GRANULARITY.TOTAL) assert len(responses.calls) == 2 assert 'granularity=TOTAL' in responses.calls[1].request.url assert stats is not None assert isinstance(stats, list) assert len(stats) == 2 assert stats[0]['id'] == 'aaaa'
def test_active_entities(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/stats/accounts/2iqph/active_entities'), body=with_fixture('active_entities'), content_type='application/json') client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') end_time = datetime.utcnow().date() start_time = end_time - timedelta(days=1) active_entities = Campaign.active_entities(account, start_time, end_time, campaign_ids=['foo', 'bar']) assert len(responses.calls) == 2 assert 'campaign_ids=foo%2Cbar' in responses.calls[1].request.url assert active_entities is not None assert isinstance(active_entities, list) assert len(active_entities) == 4 assert active_entities[0]['entity_id'] == '2mvb28'
def test_rate_limit_cursor_class_access(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '9999', 'x-account-rate-limit-reset': '1546300800' }) client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') cursor = Campaign.all(account) assert cursor is not None assert isinstance(cursor, Cursor) assert cursor.account_rate_limit_limit == '10000' assert cursor.account_rate_limit_remaining == '9999' assert cursor.account_rate_limit_reset == '1546300800'
def test_retry_count_error(monkeypatch): monkeypatch.setattr(time, 'sleep', lambda s: None) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=404, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '0', 'x-account-rate-limit-reset': str(int(time.time()) + 5) }) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=404, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '9999', 'x-account-rate-limit-reset': '1546300800' }) client = Client(characters(40), characters(40), characters(40), characters(40), options={ 'retry_max': 1, 'retry_delay': 3000, 'retry_on_status': [404, 500, 503] }) account = Account.load(client, '2iqph') try: cursor = Campaign.all(account) except Exception as e: error = e print(error) assert len(responses.calls) == 3 assert isinstance(error, NotFound)
def test_rate_limit_handle_error(monkeypatch): monkeypatch.setattr(time, 'sleep', lambda s: None) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=429, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '0', 'x-account-rate-limit-reset': str(int(time.time()) + 5) }) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=429, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '0', 'x-account-rate-limit-reset': '1546300800' }) client = Client(characters(40), characters(40), characters(40), characters(40), options={'handle_rate_limit': True}) account = Account.load(client, '2iqph') try: cursor = Campaign.all(account) except Exception as e: error = e print(error) assert len(responses.calls) == 3 assert isinstance(error, RateLimit) assert error.reset_at == '1546300800'
def test_campaign_load(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), body=with_fixture('campaigns_load'), content_type='application/json') client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') campaign = Campaign.load(account, '2wap7') assert campaign.id == '2wap7' assert campaign.entity_status == 'ACTIVE'
def test_rate_limit_resource_class_access(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), body=with_fixture('campaigns_load'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '9999', 'x-account-rate-limit-reset': '1546300800' }) client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') campaign = Campaign.load(account, '2wap7') resource = '/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7' params = {} response = Request(client, 'get', resource, params=params).perform() # from_response() is a staticmethod, so passing campaign instance as dummy. # We can later change this test case to not call this manually # once we changed existing classes to pass the header argument. data = campaign.from_response(response.body['data'], response.headers) assert data is not None assert isinstance(data, Resource) assert data.id == '2wap7' assert data.entity_status == 'ACTIVE' assert data.account_rate_limit_limit == '10000' assert data.account_rate_limit_remaining == '9999' assert data.account_rate_limit_reset == '1546300800'
def test_campaign_load(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), body=with_fixture('campaigns_load'), content_type='application/json') client = Client( characters(40), characters(40), characters(40), characters(40) ) account = Account.load(client, '2iqph') campaign = Campaign.load(account, '2wap7') assert campaign.id == '2wap7' assert campaign.entity_status == 'ACTIVE'
video.video_media_id = media_id # from previous step video.description = "My sample videos" video.title = "Video tutorial test" video.save() #grab the video_id from the response video_id = video.id print video_id account_media = AccountMedia(account) account_media.video_id = video_id account_media.creative_type = CREATIVE_TYPE.PREROLL account_media.save() # create a campaign campaign = Campaign(account) campaign.name = "Video tutorial test" # get the first funding instrument on the account campaign.funding_instrument_id = account.funding_instruments().first.id campaign.daily_budget_amount_local_micro = 1000000000 campaign.paused = True campaign.start_time = datetime.utcnow() campaign.save() # create a line item with the VIDEO_VIEWS_PREROLL # objective and product_type MEDIA line_item = LineItem(account) line_item.objective = OBJECTIVE.VIDEO_VIEWS_PREROLL line_item.campaign_id = campaign.id line_item.name = 'Video tutorial example'
from twitter_ads.enum import ENTITY_STATUS, OBJECTIVE, PLACEMENT, PRODUCT CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET = 'your consumer secret' ACCESS_TOKEN = 'access token' ACCESS_TOKEN_SECRET = 'access token secret' ACCOUNT_ID = 'account id' # initialize the client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load the advertiser account instance account = client.accounts(ACCOUNT_ID) # create your campaign campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next().id campaign.daily_budget_amount_local_micro = 1000000 campaign.name = 'my first campaign' campaign.entity_status = ENTITY_STATUS.PAUSED campaign.start_time = datetime.utcnow() campaign.save() # create a line item for the campaign line_item = LineItem(account) line_item.campaign_id = campaign.id line_item.name = 'my first ad' line_item.product_type = PRODUCT.PROMOTED_TWEETS line_item.placements = [PLACEMENT.ALL_ON_TWITTER] line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS line_item.bid_amount_local_micro = 10000
from twitter_ads.enum import ENTITY_STATUS, OBJECTIVE, PLACEMENT, PRODUCT CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET = 'your consumer secret' ACCESS_TOKEN = 'user access token' ACCESS_TOKEN_SECRET = 'user access token secret' ADS_ACCOUNT = 'ads account id' # initialize the twitter ads api client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load up the account instance account = client.accounts(ADS_ACCOUNT) # create two campaigns campaign_1 = Campaign(account) campaign_1.funding_instrument_id = account.funding_instruments().next().id campaign_1.daily_budget_amount_local_micro = 1000000 campaign_1.name = 'my first campaign' campaign_1.entity_status = ENTITY_STATUS.PAUSED campaign_1.start_time = datetime.utcnow() campaign_2 = Campaign(account) campaign_2.funding_instrument_id = account.funding_instruments().next().id campaign_2.daily_budget_amount_local_micro = 2000000 campaign_2.name = 'my second campaign' campaign_2.entity_status = ENTITY_STATUS.PAUSED campaign_2.start_time = datetime.utcnow() campaigns_list = [campaign_1, campaign_2] Campaign.batch_save(account, campaigns_list)
video.video_media_id = media_id # from previous step video.description = "My sample videos" video.title = "Video tutorial test" video.save() # grab the video_id from the response video_id = video.id print video_id account_media = AccountMedia(account) account_media.video_id = video_id account_media.creative_type = CREATIVE_TYPE.PREROLL account_media.save() # create a campaign campaign = Campaign(account) campaign.name = "Video tutorial test" # get the first funding instrument on the account campaign.funding_instrument_id = account.funding_instruments().first.id campaign.daily_budget_amount_local_micro = 1000000000 campaign.paused = True campaign.start_time = datetime.utcnow() campaign.save() # create a line item with the VIDEO_VIEWS_PREROLL # objective and product_type MEDIA line_item = LineItem(account) line_item.objective = OBJECTIVE.VIDEO_VIEWS_PREROLL line_item.campaign_id = campaign.id line_item.name = "Video tutorial example"
CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET = 'your consumer secret' ACCESS_TOKEN = 'user access token' ACCESS_TOKEN_SECRET = 'user access token secret' ADS_ACCOUNT = 'ads account id' # initialize the twitter ads api client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load up the account instance account = client.accounts(ADS_ACCOUNT) # create two campaigns campaign_1 = Campaign(account) campaign_1.funding_instrument_id = account.funding_instruments().next().id campaign_1.daily_budget_amount_local_micro = 1000000 campaign_1.name = 'my first campaign' campaign_1.paused = True campaign_1.start_time = datetime.utcnow() campaign_2 = Campaign(account) campaign_2.funding_instrument_id = account.funding_instruments().next().id campaign_2.daily_budget_amount_local_micro = 2000000 campaign_2.name = 'my second campaign' campaign_2.paused = True campaign_2.start_time = datetime.utcnow() campaigns_list = [campaign_1, campaign_2] Campaign.batch_save(account, campaigns_list)
CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET = 'your consumer secret' ACCESS_TOKEN = 'access token' ACCESS_TOKEN_SECRET = 'access token secret' ACCOUNT_ID = 'account id' # initialize the client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load the advertiser account instance account = client.accounts(ACCOUNT_ID) # create your campaign campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next().id campaign.daily_budget_amount_local_micro = 1000000 campaign.name = 'my first campaign' campaign.entity_status = ENTITY_STATUS.PAUSED campaign.start_time = datetime.utcnow() campaign.save() # create a line item for the campaign line_item = LineItem(account) line_item.campaign_id = campaign.id line_item.name = 'my first ad' line_item.product_type = PRODUCT.PROMOTED_TWEETS line_item.placements = [PLACEMENT.ALL_ON_TWITTER] line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS line_item.bid_amount_local_micro = 10000
from twitter_ads.enum import PRODUCT, PLACEMENT, OBJECTIVE CONSUMER_KEY = 'UNzAQw4xoXvegTHWomkiJZbwH' CONSUMER_SECRET = 'ynpaidBbGNkY6TuFn0v9brGjhpLTjIuEakqddyMqeHrh9WswqO' ACCESS_TOKEN = '443463608-o3vgnvAWxO3tHZzyl7Yw6ifLJXNp4ukN2Gp4nZhh' ACCESS_TOKEN_SECRET = 'EcXHIhWDD2xXe5GPoaWoNllMY3Z2wBhwM8XUdM9CkSaC9' ACCOUNT_ID = '443463608' # initialize the client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load the advertiser account instance account = client.accounts(ACCOUNT_ID) # create your campaign campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next().id campaign.daily_budget_amount_local_micro = 1000000 campaign.name = 'my first campaign' campaign.paused = True campaign.start_time = datetime.datetime.utcnow() campaign.save() # create a line item for the campaign line_item = LineItem(account) line_item.campaign_id = campaign.id line_item.name = 'my first ad' line_item.product_type = PRODUCT.PROMOTED_TWEETS line_item.placements = [PLACEMENT.ALL_ON_TWITTER] line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS
def test_rate_limit_handle_with_retry_success_2(monkeypatch): # scenario: # - 429 (handle rate limit) -> 500 (retry) -> 200 (end) monkeypatch.setattr(time, 'sleep', lambda s: None) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=429, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '0', 'x-account-rate-limit-reset': '1546300800' }) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=500, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '0', 'x-account-rate-limit-reset': str(int(time.time()) + 5) }) responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), status=200, body=with_fixture('campaigns_all'), content_type='application/json', headers={ 'x-account-rate-limit-limit': '10000', 'x-account-rate-limit-remaining': '9999', 'x-account-rate-limit-reset': '1546300800' }) client = Client(characters(40), characters(40), characters(40), characters(40), options={ 'handle_rate_limit': True, 'retry_max': 1, 'retry_delay': 3000, 'retry_on_status': [500] }) account = Account.load(client, '2iqph') cursor = Campaign.all(account) assert len(responses.calls) == 4 assert cursor is not None assert isinstance(cursor, Cursor) assert cursor.account_rate_limit_limit == '10000' assert cursor.account_rate_limit_remaining == '9999' assert cursor.account_rate_limit_reset == '1546300800'
from twitter_ads.enum import PRODUCT, PLACEMENT, OBJECTIVE CONSUMER_KEY = "your consumer key" CONSUMER_SECRET = "your consumer secret" ACCESS_TOKEN = "user access token" ACCESS_TOKEN_SECRET = "user access token secret" ADS_ACCOUNT = "ads account id" # initialize the twitter ads api client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load up the account instance account = client.accounts(ADS_ACCOUNT) # create two campaigns campaign_1 = Campaign(account) campaign_1.funding_instrument_id = account.funding_instruments().next().id campaign_1.daily_budget_amount_local_micro = 1000000 campaign_1.name = "my first campaign" campaign_1.paused = True campaign_1.start_time = datetime.utcnow() campaign_2 = Campaign(account) campaign_2.funding_instrument_id = account.funding_instruments().next().id campaign_2.daily_budget_amount_local_micro = 2000000 campaign_2.name = "my second campaign" campaign_2.paused = True campaign_2.start_time = datetime.utcnow() campaigns_list = [campaign_1, campaign_2] Campaign.batch_save(account, campaigns_list)
CONSUMER_KEY = 'your consumer key' CONSUMER_SECRET = 'your consumer secret' ACCESS_TOKEN = 'access token' ACCESS_TOKEN_SECRET = 'access token secret' ACCOUNT_ID = 'account id' # initialize the client client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) # load the advertiser account instance account = client.accounts(ACCOUNT_ID) # create your campaign campaign = Campaign(account) campaign.funding_instrument_id = account.funding_instruments().next().id campaign.daily_budget_amount_local_micro = 1000000 campaign.name = 'my first campaign' campaign.paused = True campaign.start_time = datetime.utcnow() campaign.save() # create a line item for the campaign line_item = LineItem(account) line_item.campaign_id = campaign.id line_item.name = 'my first ad' line_item.product_type = PRODUCT.PROMOTED_TWEETS line_item.placements = [PLACEMENT.ALL_ON_TWITTER] line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS line_item.bid_amount_local_micro = 10000
video.video_media_id = media_id # from previous step video.description = "My sample videos" video.title = "Video tutorial test" video.save() #grab the video_id from the response video_id = video.id print video_id account_media = AccountMedia(account) account_media.video_id = video_id account_media.creative_type = CREATIVE_TYPE.PREROLL account_media.save() # create a campaign campaign = Campaign(account) campaign.name = "Video tutorial test" # get the first funding instrument on the account campaign.funding_instrument_id = account.funding_instruments().first.id campaign.daily_budget_amount_local_micro = 1000000000 campaign.entity_status = ENTITY_STATUS.PAUSED campaign.start_time = datetime.utcnow() campaign.save() # create a line item with the VIDEO_VIEWS_PREROLL # objective and product_type MEDIA line_item = LineItem(account) line_item.objective = OBJECTIVE.VIDEO_VIEWS_PREROLL line_item.campaign_id = campaign.id line_item.name = 'Video tutorial example'
def test_analytics_async(): responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'), body=with_fixture('accounts_load'), content_type='application/json') responses.add(responses.POST, with_resource('/' + API_VERSION + '/stats/jobs/accounts/2iqph'), body=with_fixture('analytics_async_post'), content_type='application/json', headers={ 'x-concurrent-job-limit': '100', 'x-concurrent-job-limit-remaining': '99' }) responses.add(responses.GET, with_resource('/' + API_VERSION + '/stats/jobs/accounts/2iqph'), body=with_fixture('analytics_async_get'), content_type='application/json') client = Client(characters(40), characters(40), characters(40), characters(40)) account = Account.load(client, '2iqph') ids = ['aaaa'] metric_groups = [METRIC_GROUP.ENGAGEMENT] stats = Campaign.queue_async_stats_job(account, ids, metric_groups, granularity=GRANULARITY.TOTAL) # call queue_async_stats_job() through Campaign class (inheritance) assert 'granularity=TOTAL' in responses.calls[1].request.url assert stats is not None assert isinstance(stats, Analytics) assert stats.entity_ids == ids assert stats.concurrent_job_limit == '100' stats2 = Analytics.queue_async_stats_job(account, ids, metric_groups, granularity=GRANULARITY.TOTAL, entity=ENTITY.CAMPAIGN) # call queue_async_stats_job() from Analytics class directly assert 'entity=CAMPAIGN' in responses.calls[1].request.url assert stats2 is not None assert isinstance(stats2, Analytics) assert stats2.entity_ids == ids assert stats2.concurrent_job_limit == '100' # call async_stats_job_result() through Campaign class (inheritance) job_id = stats.id_str job_result = Campaign.async_stats_job_result(account, job_ids=[job_id]).first assert job_result is not None assert isinstance(job_result, Analytics) assert job_result.url == 'https://ton.twimg.com/advertiser-api-async-analytics/stats.json.gz' # call async_stats_job_result() from Analytics class directly job_result = Analytics.async_stats_job_result(account, job_ids=[job_id]).first assert job_result is not None assert isinstance(job_result, Analytics) assert job_result.url == 'https://ton.twimg.com/advertiser-api-async-analytics/stats.json.gz'