Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@
license='Apache',
author='Timu Eren',
author_email='selamtux@gmail.com',
description="Easy way to generate vast (3.0) xml"
description="Easy way to generate vast (3.0) xml",
install_requires=[
'lxml'
]
)
33 changes: 19 additions & 14 deletions vast/ad.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from creative import Creative
from .creative import Creative


REQUIRED_INLINE = ['AdSystem', 'AdTitle']
REQUIRED_WRAPPER = ['AdSystem', 'VASTAdTagURI']
REQUIRED_INLINE = ['id', 'ad_system', 'ad_title']
REQUIRED_WRAPPER = ['id', 'ad_system', 'vast_ad_tag_uri']


def validateSettings(settings, requireds):
Expand All @@ -43,26 +43,27 @@ def __init__(self, settings={}):
self.surveys = []
self.impressions = []
self.creatives = []
self.extensions = []

if settings["structure"].lower() == 'wrapper':
validateWrapperSettings(settings)
self.VASTAdTagURI = settings["VASTAdTagURI"]
self.vast_ad_tag_uri = settings["vast_ad_tag_uri"]
self.ad_title = settings.get("ad_title", None)
else:
validateInLineSettings(settings)
self.ad_title = settings["ad_title"]

self.id = settings["id"]
self.sequence = settings.get("sequence", None)
self.structure = settings["structure"]
self.AdSystem = settings["AdSystem"]
self.AdTitle = settings["AdTitle"]
self.ad_system = settings["ad_system"]

# optional elements
self.Error = settings.get("Error", None)
self.Description = settings.get("Description", None)
self.Advertiser = settings.get("Advertiser", None)
self.sequence = settings.get("sequence", None)
self.error = settings.get("error", None)
self.description = settings.get("description", None)
self.avertiser = settings.get("advertiser", None)

self.Pricing = settings.get("Pricing", None)
self.Extensions = settings.get("Extensions", None)
self.pricing = settings.get("pricing", None)

def attachSurvey(self, settings):
survey={"url": settings.url}
Expand All @@ -74,8 +75,12 @@ def attachImpression(self, settings):
self.impressions.append(settings)
return self

def attachCreative(self, _type, options):
creative = Creative(_type, options)
def attachCreative(self, creative_type, options):
creative = Creative(creative_type, options)
self.creatives.append(creative)
return creative

def attachExtension(self, extension_type, xml):
self.extensions.append({"type": extension_type, "xml": xml})
return self

2 changes: 1 addition & 1 deletion vast/companionAd.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from trackingEvent import TrackingEvent
from .trackingEvent import TrackingEvent


class CompanionAd(object):
Expand Down
74 changes: 44 additions & 30 deletions vast/creative.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,40 @@
# limitations under the License.


from companionAd import CompanionAd
from icon import Icon
from trackingEvent import TrackingEvent
from .companionAd import CompanionAd
from .icon import Icon
from .trackingEvent import TrackingEvent

VALID_VIDEO_CLICKS = ['ClickThrough', 'ClickTracking', 'CustomClick']
VALID_CREATIVE_TYPES = ['Linear', 'NonLinear', 'CompanionAds']
REQUIRED_MEDIA_ATTRIBUTES = ['type', 'width', 'height', 'delivery']


class Creative(object):
def __init__(self, _type, settings=None):
def __init__(self, creative_type, settings=None):
if creative_type not in VALID_CREATIVE_TYPES:
raise Exception('The supplied creative type is not a valid VAST creative type.')

settings = {} if settings is None else settings
self.type = _type
self.type = creative_type
self.mediaFiles = []
self.trackingEvents = []
self.videoClicks = []
self.clickThroughs = []
self.clicks = []
self.resources = []
self.icons = []
self.AdParameters = settings.get("AdParameters", None)
self._adParameters = None
self.ad_parameters = settings.get("adParameters", None)
self.attributes = {}
self.duration = settings.get("Duration", None)
self.duration = settings.get("duration", None)
self.skipoffset = settings.get("skipoffset", None)
self.nonLinearClickEvent = None

if _type == "Linear" and self.duration is None:
if creative_type == "Linear" and self.duration is None:
raise Exception('A Duration is required for all creatives. Consider defaulting to "00:00:00"')

if "id" in settings:
self.attributes["id"] = settings["id"]

if "width" in settings:
self.attributes["width"] = settings["width"]
if "height" in settings:
Expand All @@ -65,16 +68,20 @@ def __init__(self, _type, settings=None):
self.attributes["apiFramework"] = settings["apiFramework"]

def attachMediaFile(self, url, settings={}):
keys = settings.keys()
for required in REQUIRED_MEDIA_ATTRIBUTES:
if required not in keys:
raise Exception("MediaFile missing required settings: {required}".format(required=required))

media_file = {"attributes": {}}
media_file["url"] = url
media_file["attributes"]["type"] = settings.get("type", 'video/mp4')
media_file["attributes"]["width"] = settings.get("width",'640')
media_file["attributes"]["height"] = settings.get("height", '360')
media_file["attributes"]["delivery"]= settings.get("delivery", 'progressive')
if "id" not in settings:
raise Exception('an `id` is required for all media files')

media_file["attributes"]["id"] = settings["id"]
media_file["attributes"]["type"] = settings.get("type")
media_file["attributes"]["width"] = settings.get("width")
media_file["attributes"]["height"] = settings.get("height")
media_file["attributes"]["delivery"]= settings.get("delivery")

if "id" in settings:
media_file["attributes"]["id"] = settings["id"]
if "bitrate" in settings:
media_file["attributes"]["bitrate"] = settings["bitrate"]
if "minBitrate" in settings:
Expand All @@ -93,32 +100,39 @@ def attachMediaFile(self, url, settings={}):
self.mediaFiles.append(media_file)
return self

def attachTrackingEvent(self, _type, url, offset=None):
self.trackingEvents.append(TrackingEvent(_type, url, offset))
def attachTrackingEvent(self, event_type, url, offset=None):
self.trackingEvents.append(TrackingEvent(event_type, url, offset))
return self

def attachVideoClick(self, _type, url, _id=''):
if _type not in VALID_VIDEO_CLICKS:
def attachVideoClick(self, click_type, url, click_id=''):
if click_type not in VALID_VIDEO_CLICKS:
raise Exception('The supplied VideoClick `type` is not a valid VAST VideoClick type.')
self.videoClicks.append({"type": _type, "url": url, "id": _id})

self.videoClicks.append({"type": click_type, "url": url, "id": click_id})

return self

def attachClickThrough(self, url):
self.clickThroughs.append(url)
return self

def attachClick(self, uri, _type=None):
def attachClick(self, uri, click_type=None):
if isinstance(uri, basestring):
_type = 'NonLinearClickThrough'
self.clicks = [{"type": _type, "uri": uri}]
click_type = 'NonLinearClickThrough'

self.clicks = [{"type": click_type, "uri": uri}]

return self

def attachResource(self, _type, uri, creative_type=None):
resource = {"type": _type, "uri": uri}
if _type == 'HTMLResource':
def attachResource(self, resource_type, uri, creative_type=None):
resource = {"type": resource_type, "uri": uri}

if resource_type == 'HTMLResource':
resource["html"] = uri

if creative_type is not None:
resource["creativeType"] = creative_type

self.resources.append(resource)
return self

Expand All @@ -128,7 +142,7 @@ def attachIcon(self, settings):
return icon

def adParameters(self, data, xml_encoded):
self._adParameters = {"data": data, "xmlEncoded": xml_encoded}
self.ad_parameters = {"data": data, "xmlEncoded": xml_encoded}
return self

def attachNonLinearClickTracking(self, url):
Expand Down
15 changes: 9 additions & 6 deletions vast/icon.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
# limitations under the License.


REQURED_ATTRIBUTES = ["program", "width", "height", "xPosition", "yPosition"]
REQUIRED_ATTRIBUTES = ["program", "width", "height", "xPosition", "yPosition"]


class Icon(object):
def __init__(self, settings=dict()):
keys = settings.keys()
for required in keys:
for required in REQUIRED_ATTRIBUTES:
if required not in keys:
raise Exception("Missing required attribute '{attr}'".format(attr=required))

Expand All @@ -33,15 +33,18 @@ def __init__(self, settings=dict()):
self.click = None
self.view = None

def setResource(self, _type, uri, creativeType=None):
if _type not in ('StaticResource', "IFrameResource", "HTMLResource"):
def setResource(self, resource_type, uri, creativeType=None):
if resource_type not in ('StaticResource', "IFrameResource", "HTMLResource"):
raise Exception("Invalid resource type")

resource = {"type": _type, "uri": uri}
if _type == 'HTMLResource':
resource = {"type": resource_type, "uri": uri}

if resource_type == 'HTMLResource':
resource["html"] = uri

if creativeType:
resource["creativeType"] = creativeType

self.resource = resource

def setClickThrough(self, uri):
Expand Down
Loading