Package: bebanjo-api-hi2meuk
Bebanjo API clientA client library interfacing to Bebanjo's Movida and Sequence APIs allowing integration developers to focus on the business logic of their application and not the low level detail.The library provides support for authentication, exception handling, logging and utilities for common tasks. It can be used in an interactive session. By design it is very loosely coupled to Movida/Sequence schemas.Example ApplicationTo demonstrate some features, here is an application to upload an image on all titles scheduled on platformAndroid GBand target them for that platform and set them as thepost artfor that title in the Movida UI.frombebanjoimportMovidaAPImapi=MovidaAPI(env='staging')IMAGE_URL='tests/image/1yeVJox3rjo2jBKrrihIMj7uoS9.JPEG'platforms=mapi.platforms.fetch()target_platform=filter(lambdap:p.name=='Android GB',platforms)[0]fortitleintarget_platform.titles.get_paginated():image=title.images.create_image(IMAGE_URL,meta1={'IsPosterArt':True})image.target_platforms.create(target_platform.url)Although this would work as described, a well designed application would also include exception handling, checking if the image already exists and logging to file.InstallationPyPIpipinstall--userbebanjo-apiGITVisitbebanjo-apiinGitLabto clone and contribute to the project.Using the Bebanjo client librarySetting up your applicationfrombebanjoimportMovidaAPI,install_auth_handlersRobot account credentialsThe authentication handler must be initialised with login data for the Bebanjo environments used.  The library assumes there no distinction between Sequence and Movida credentials. The format of the credentials to be supplied to the handler initialisation is a nested dict as follows:config={'staging':{'name':'robot_hi2meuk','password':'mypassword'}}The environment key(s) must be one of:staging,preproductionorproduction.Setup the authentication handler before instantiating an API providing a config data structure as previously described:install_auth_handlers(config)A function is provided by the library to setup the auth config based on a local JSON file.frombebanjo.utilsimportread_local_configconfig=read_local_config(CONFIG_FILE)The config file must be in JSON format. If a file path is not supplied, the default is ".bebanjo.json" in users home directory (Windows or Linux).Create a Movida API instance for your chosen environmentmapi=MovidaAPI(env='staging')It is possible to specify a local Wiremock server to emulate Movida/Sequence for component testing purposes:mock_url='http://localhost:8080/api'mapi=MovidaAPI(url=mock_url)LoggingAPI calls made and responses are logged using thepython logging framework.Logs are generated at debug level containing the XML payloads sent and received.  Console output only includes logs of severity WARNINGS and above. This is a characteristic of the logging framework.  The following code placed in the application will enable DEBUG to the console with in the format specified.ch=logging.StreamHandler()ch.setLevel(logging.DEBUG)formatter=logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')ch.setFormatter(formatter)logger.addHandler(ch)Principals of useFetch first to discover what the next thing doesImagine you are to navigate the Movida API and youronlyknowledge and starting point is the root:/api. You would first have to do a GET call that resource to find it contains other collection resources (REST collection) liketitlesandtitle_groupsand others.  If you made a GET call on thetitlesresource you will notice it has numerous metadata keys and values andlinksto other collection resources including extendedMetadata. Likewise, you would have to do a GET call on those resources e.g.assetsto know what sort of resources it has.The same applies to using this client library, often we have to do a fetch to access the properties beyond the API root.This approach means the library is loosely coupled to Movida. If there are changes in Movida schema it is unlikely to require an update to this library.  it also means you do not have to tell the library about your companies custom metadata; the library will discover it and make it available to your application.Except, no need to fetch root/api resourceThere are exceptions to this "fetch first" principal. Because fetching the API is a common starting point and what it contains is very predictable, the library pre-populates the properties of the root API object, e.g. it already has atitlesproperty:mapi=MovidaAPI(env='staging')title=mapi.fetch(1001)Except, don't need to fetch the schedulings resource - use add_link() insteadIf you want to avoid unnecessary GET calls when you know the next item beyond the current URL path, you can patch it in to your object.  A common use case is the schedule resource; when you fetch it, you find it only contains a link to the schedulings resource and nothing else.  We can add the schedulings resource directly and save a GET call.mapi=MovidaAPI(env='staging')title=titles.fetch(1001)schedulings=title.schedule.add_link('schedulings').fetch()FeaturesMemory efficient Collection processingThe get_paginated() method of a collection resource e.g. titles is a python generator.  It will iterate through each title of the resource returning each title at a time.  It will make the GET calls to Movida one page at a time as and when needed (by default with a page size of 50). Only the page of items is held in memory within the collection object at any time.platform=mapi.platforms.fetch(101)titles=platform.titles.get_paginated()fortitleintitles:print(title.name)Image creation and setting the target platformsImages can be uploaded from a local file or from a remote server location, the method will be determined from the file path given to thecreate_image()method.  The return value is an image object representing the created image.  Images can be created from a pre-fetched or post fetched object.  The encoding type and file name are by default extracted from the given image file name but can be overridden by passing in a dict object.  Other metadata can also be passed in.  Movida will set values for size and MD5 checksum when the file is processed - this is done asynchronously for remotely sourced images and will be empty in the locally created object.IMAGE_PATH_LOCAL='tests/image/1yeVJox3rjo2jBKrrihIMj7uoS9.JPEG'mapi=MovidaAPI(env='staging')title=titles.fetch(1001)image=title.images.create_image(IMAGE_PATH_REMOTE)image.target_platforms.add_platforms(['https://movida.bebanjo.net/api/platforms/51','api/platforms/52',53])A remote path is also supported.IMAGE_PATH_REMOTE='https://mydomain.com/image/1yeVJox3rjo2jBKrrihIMj7uoS9.jpg'For existing images there is a risk the addition of a target_platform will fail if it already exists on the image.images=title.images.fetch()forimageinimages:ifimage.type==SELECTED_IMAGE_TYPE:image=image.fetch()image.target_platforms.add_platforms(TARGET_PLATFORMS)# will fail if any exists alreadyTo avoid the possible failure do:image=image.fetch()image.target_platforms=image.target_platforms.fetch()# get existing target platformsimage.target_platforms.add_platforms(TARGET_PLATFORMS)# will not add platform if already existsNote the long code line in the above:image.target_platforms=image.target_platforms.fetch()This is necessary when target_platforms is of class Fetcher; it cannotupgradeits own class to Collection.  A helper is available to make the code a little cleaner.frombebanjo.utilsimportreplace_self_fetchreplace_self_fetch(image.target_platforms)Seamlessly step between Movida and SequenceAs long as you have valid credentials loaded that are valid for Movida and Sequence, then the library does is agnostic to the resource referenced in an object property. E.g. the jobs resource on a Movida scheduling refers to a resource in Sequence and accessing that resource will automatically trigger authentication with Sequence.String representations of an objectInspect utilityInspect the properties of a title; first class metadata, extended metadata and links to related objects that can be fetched for further inspection.  It prints directly to the console.  It is intended for debugging and interactive sessions.frombebanjoimportinspectinspect(title)Output:Instance of Title (//titles/1001)
 > name: Winter Is Coming
 > title: Winter Is Coming
 > external_id: 63056
 > title_type: 'episode
 > episode_number: 1
 > tags:
 Metadata:
 > short_description: The "one" where winter's comming
 > air_date: 2011-04-24
 > content_source: The Movie Database
 > subgenres: ['Action', 'Fantasy']
 > download_rights: True
 Getters:
 > assets
 > availability_windows
 > blackouts
 > images
 > licensor
 > linear_schedulings
 > metadata
 > rights
 > rules
 > schedule
 > title_groups
 > trailersFetch a title by external IDtitle=mapi.titles.fetch(1001)Fetch title by external_id and include extended metadata and imagestitle=mapi.titles.fetch(external_id='HI2MEUK/377364',expand=['metadata','images'])Fetch asset by nameasset=mapi.assets.fetch(name='BBJ12345A')Create an object using the parent resource objectNo need to fetch the collection resource first as only it's URL is needed to create an object inside this resource.mapi=MovidaAPI(env='staging')meta={'name':'The Ring'}relations={'licensor':'api/licensors/4'}mapi.titles.create(meta,relations)In the above example, if name were not specified, Movida would complain with a 422 response becausenameis mandatory for a title.  Likewise if a metadata key or value is invalid, a 422 response would also result.Read the metadata of an objectAccess the values of metadata like they're python dictionary.# first class metadataname=title['name']# extended metadatadescription=title.metadata['description']Update a title in Movida# first class metadatatitle.update({'name':'The Ring'},{'licensor':'api/licensors/1201'})# extended metadata requires a seperate call to Movidatitle.metadata.update({'name':'abcdéf','description':'Simon looses the ring.'})Build a dict of platform names to IDsid_from_platform={}forplatforminmapi.platforms.fetch():id_from_platform[platform.name]=platform.id