diff --git a/line_item_manager/__init__.py b/line_item_manager/__init__.py index 5a116c5..f1c42bd 100644 --- a/line_item_manager/__init__.py +++ b/line_item_manager/__init__.py @@ -5,7 +5,7 @@ __version__ = '0.2.3' # For an official release, use dev_version = '' -dev_version = '1' +dev_version = '2' version = __version__ if dev_version: diff --git a/line_item_manager/conf.d/line_item_manager.yml b/line_item_manager/conf.d/line_item_manager.yml index 14d3828..4e7c6e6 100644 --- a/line_item_manager/conf.d/line_item_manager.yml +++ b/line_item_manager/conf.d/line_item_manager.yml @@ -76,6 +76,7 @@ creative: # at least one of the following types is required {video, banner} - height: 240 width: 320 vast_xml_url: "https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:{{ hb_uuid }}%%" + # max_duration: 60000 # optional: defaults to 30000, see settings.yml ############################################################################### # Orders (required) # Allowed Templating Key Words: Bidder, Media, Order, Misc diff --git a/line_item_manager/conf.d/line_item_template.yml b/line_item_manager/conf.d/line_item_template.yml index 6c2d68a..5685bf1 100644 --- a/line_item_manager/conf.d/line_item_template.yml +++ b/line_item_manager/conf.d/line_item_template.yml @@ -29,6 +29,7 @@ creativePlaceholders: {% if li.media_type == 'video' %} environmentType: "VIDEO_PLAYER" companionDeliveryOption: "OPTIONAL" +videoMaxDuration: {{ user_cfg.creative[li.media_type].max_duration }} {% endif %} {% if user_cfg.line_item.goal %} diff --git a/line_item_manager/conf.d/schema.yml b/line_item_manager/conf.d/schema.yml index 838835d..a12368c 100644 --- a/line_item_manager/conf.d/schema.yml +++ b/line_item_manager/conf.d/schema.yml @@ -27,6 +27,8 @@ properties: $ref: "#/definitions/sizeArray" vast_xml_url: type: "string" + max_duration: + type: "#/definitions/positiveIntegerType" required: - "sizes" - "vast_xml_url" @@ -213,6 +215,9 @@ definitions: - 'auto' - 'dense' - 'custom' + positiveIntegerType: + type: "integer" + minimum: 1 priorityType: type: "integer" minimum: 1 diff --git a/line_item_manager/conf.d/settings.yml b/line_item_manager/conf.d/settings.yml index 01cbb91..317005d 100644 --- a/line_item_manager/conf.d/settings.yml +++ b/line_item_manager/conf.d/settings.yml @@ -44,6 +44,7 @@ prebid: height: 1 width: 1 video: + max_duration: 30000 # milliseconds duration: 1000 # milliseconds price_granularity: low: diff --git a/line_item_manager/config.py b/line_item_manager/config.py index 1ba583e..c9ebaf5 100644 --- a/line_item_manager/config.py +++ b/line_item_manager/config.py @@ -149,6 +149,12 @@ def pre_create(self) -> None: fmt = self.app['mgr']['date_fmt'] vcpm = self.user['rate'].get('vcpm') + if self.user['creative'].get('video'): + _ = self.user['creative']['video'].setdefault( + 'max_duration', + self.app['prebid']['creative']['video']['max_duration'] + ) + if vcpm and not is_standard: raise ValueError("Specifying 'vcpm' requires using line item type 'standard'") diff --git a/tests/resources/cfg_video_max_duration.yml b/tests/resources/cfg_video_max_duration.yml new file mode 100644 index 0000000..6894c92 --- /dev/null +++ b/tests/resources/cfg_video_max_duration.yml @@ -0,0 +1,131 @@ +# line_item_manager configuration +############################################################################### +# Templating uses jinja2 rendering (see https://palletsprojects.com/p/jinja/) +# The following key word types are supported: +# Bidder: +# bidder_code = bidder-code +# bidder_name = bidder-name +# hb_ = hb__ (20 char limit) +# CPM: +# cpm = line item rate as cost-per-thousand impressions +# Media: +# media_type = video or banner based on creative configuration below +# Misc: +# time = current UTC time represented as "%m/%d/%Y %H:%M:%S" +# Order: +# cpm_max = order maximum cpm +# cpm_min = order minimum cpm +# +# See https://docs.prebid.org/dev-docs/bidder-data.csv for referencing bidder +# names and codes. +############################################################################### +# Publisher (optional) +# This can be specified at run-time like this: +# --network-code +# --network-name +# +publisher: + network_code: 1234 + network_name: "Video Publisher" +############################################################################### +# Advertiser (required) +# Allowed Templating Key Words: Bidder +############################################################################### +advertiser: + name: "Prebid" +############################################################################### +# Creatives (required) +# Allowed Templating Key Words: Bidder, Media, Misc +############################################################################### +creative: # at least one of the following types is required {video, banner} + name: "Prebid {{ bidder_name }}-{{ media_type }}" + video: + sizes: # list + - height: 480 + width: 640 + - height: 240 + width: 320 + vast_xml_url: "https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:{{ hb_cache_id }}%%" + max_duration: 60000 + banner: + sizes: # list + - height: 480 + width: 640 + snippet: | + + + # safe_frame: False (optional: defaults to True) +############################################################################### +# Orders (required) +# Allowed Templating Key Words: Bidder, Media, Order, Misc +############################################################################### +order: + name: "Prebid-{{ bidder_name }}-{{ media_type }}-{{ time }} {{ cpm_min }}-{{ cpm_max }}" + appliedTeamIds: # list (optional) + - 12345678 + - 23456789 +############################################################################### +# Line Items (required) +# Allowed Templating Key Words: Bidder, Media, CPM, Misc +# +# Supported Types: price_priority, standard +# datetimes use: "%m/%d/%y %H:%M" (ex. 11/17/20 21:28) +# - default timezone is UTC +# timezones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +############################################################################### +line_item: + name: "Prebid-{{ bidder_name }}-{{ media_type }}-{{ time }} @ {{ cpm }}" + item_type: "price_priority" + # Optional + # start_datetime: "11/17/20 21:28" + # end_datetime: "12/17/20 21:28" + # timezone: "UTC" +############################################################################### +# Bidder Targeting Key Override Map (optional): +# If provided override the default bidder_targeting_key and use these +# targeting keys specified by bidder_code. +# +# bidder_key_map: +# : +# : +############################################################################### +# Targeting (required) +# Allowed Templating Key Words: None +# +# Note: A Key-Value of 'bidder_targeting_key' with all CPM values is created +# by default. +############################################################################### +targeting: + custom: # list (optional) + - name: "country" + values: + - "US" + - "CAN" + # One of the below either placemane_names or ad_unit_names is required + placement_names: # list of names + - "placement name 1" + - "placement name 2" + ad_unit_names: # list of names + - "ad unit name 1" + - "ad unit name 2" +############################################################################### +# Rate (required) +# NOTE: granularity in Prebid.js config must align with this granularity +# Allowed Templating Key Words: None +############################################################################### +rate: + currency: "USD" # required + granularity: + type: "custom" + custom: + - min: 0.10 + max: 0.30 + interval: 0.10 + - min: 0.30 + max: 1.30 + interval: 0.50 + # optional properties + # vcpm: 100000 # viewable impressions will be enabled + diff --git a/tests/resources/video_expected.yml b/tests/resources/video_expected.yml index c243810..b082f5b 100644 --- a/tests/resources/video_expected.yml +++ b/tests/resources/video_expected.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -47,6 +48,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 diff --git a/tests/resources/video_expected_dry_run.yml b/tests/resources/video_expected_dry_run.yml index 207c467..6a0d500 100644 --- a/tests/resources/video_expected_dry_run.yml +++ b/tests/resources/video_expected_dry_run.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -12,7 +13,7 @@ width: 320 creativeRotationType: EVEN environmentType: VIDEO_PLAYER - id: 9999827713 + id: 9999899367 lineItemType: PRICE_PRIORITY name: Prebid-InteractiveOffers-video-01/02/2020-08:09:10 @ 1.25 orderId: 6001 @@ -47,6 +48,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 @@ -60,7 +62,7 @@ width: 320 creativeRotationType: EVEN environmentType: VIDEO_PLAYER - id: 9999224642 + id: 9999960551 lineItemType: PRICE_PRIORITY name: Prebid-InteractiveOffers-video-01/02/2020-08:09:10 @ 1.50 orderId: 6001 diff --git a/tests/resources/video_expected_no_targeting.yml b/tests/resources/video_expected_no_targeting.yml index 80f2916..b232b84 100644 --- a/tests/resources/video_expected_no_targeting.yml +++ b/tests/resources/video_expected_no_targeting.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -38,6 +39,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 diff --git a/tests/resources/video_expected_one_custom_value.yml b/tests/resources/video_expected_one_custom_value.yml index 57d6ca4..c72d1e9 100644 --- a/tests/resources/video_expected_one_custom_value.yml +++ b/tests/resources/video_expected_one_custom_value.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -46,6 +47,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 diff --git a/tests/resources/video_expected_test_run.yml b/tests/resources/video_expected_test_run.yml index 10319c8..177a953 100644 --- a/tests/resources/video_expected_test_run.yml +++ b/tests/resources/video_expected_test_run.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -47,6 +48,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 diff --git a/tests/resources/video_single_order_expected.yml b/tests/resources/video_single_order_expected.yml index 45f04b5..54d7381 100644 --- a/tests/resources/video_single_order_expected.yml +++ b/tests/resources/video_single_order_expected.yml @@ -1,4 +1,5 @@ - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1250000 @@ -47,6 +48,7 @@ targetedRequestPlatforms: VIDEO_PLAYER unlimitedEndDateTime: true - companionDeliveryOption: OPTIONAL + videoMaxDuration: 30000 costPerUnit: currencyCode: USD microAmount: 1500000 diff --git a/tests/test_config.py b/tests/test_config.py index 895a9dd..8f489a5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -80,3 +80,7 @@ def test_custom_targeting_is_not_reportableType(cli_config): assert config.custom_targeting_key_values() == \ [{'name': 'country', 'values': {'CAN', 'US'}, 'operator': 'IS_NOT', 'reportableType': 'ON'}] assert config.targeting_bidder_key_config() == {'reportableType': 'ON'} + +@pytest.mark.command(f'create tests/resources/cfg_video_max_duration.yml -k {KEY_FILE} -b ix -q') +def test_video_max_duration(cli_config): + assert config.user['creative']['video']['max_duration'] == 60000 diff --git a/tests/test_create.py b/tests/test_create.py index 02606ba..b8b3599 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -50,10 +50,10 @@ CREATIVE_1 = int('9999' + str(num_hash(['CreativeVideo', str(VIDEO_CREATIVE)]))) DRY_RUN_EXPECTED_LICA = \ - [[{'lineItemId': 9999827713, 'creativeId': CREATIVE_0, 'id': 9999534789}, - {'lineItemId': 9999827713, 'creativeId': CREATIVE_1, 'id': 9999840404}, - {'lineItemId': 9999224642, 'creativeId': CREATIVE_0, 'id': 9999813993}, - {'lineItemId': 9999224642, 'creativeId': CREATIVE_1, 'id': 9999825404}]] + [[{'lineItemId': 9999899367, 'creativeId': CREATIVE_0, 'id': 9999164843}, + {'lineItemId': 9999899367, 'creativeId': CREATIVE_1, 'id': 9999863541}, + {'lineItemId': 9999960551, 'creativeId': CREATIVE_0, 'id': 9999333772}, + {'lineItemId': 9999960551, 'creativeId': CREATIVE_1, 'id': 9999408383}]] BANNER_EXPECTED_LICA = \ [[{'lineItemId': 8001, 'creativeId': 4001, 'sizes': [{'height': 20, 'width': 1000}], 'id': 9001},