From 9fe532252e51447d481d15e8cb1f9d208d1633e2 Mon Sep 17 00:00:00 2001 From: Dylan Andrade Date: Thu, 7 Dec 2023 14:54:20 +0100 Subject: [PATCH] API-1821 Implement Sample Files for PYTHON-SDK Functionality Testing (#39) * API-1821 Implement Sample Files for PYTHON-SDK Functionality Testing * API-1821 Dockerize testing sample * API-1821 Update README with instructions * API-1821 Add details to README * API-1821 add run docker to Makefile * API-1821 fixed example on secret.example.json * API-1821 add comment on example * API-1821 Add more examples to collections --- .gitignore | 6 +++ Dockerfile | 11 +++++ Makefile | 13 ++++++ README.md | 46 +++++++++++++++++++++ docker-compose.yaml | 8 ++++ {example => samples}/app.py | 0 samples/brands.py | 14 +++++++ samples/campaign.py | 52 +++++++++++++++++++++++ samples/client.py | 48 ++++++++++++++++++++++ samples/collection.py | 62 ++++++++++++++++++++++++++++ {example => samples}/image.png | Bin samples/media.py | 43 +++++++++++++++++++ samples/metaproperties.py | 14 +++++++ samples/pim_metaproperties.py | 30 ++++++++++++++ samples/tags.py | 14 +++++++ samples/upload_file.py | 25 +++++++++++ samples/workflow_group.py | 22 ++++++++++ samples/workflow_jobs.py | 64 +++++++++++++++++++++++++++++ samples/workflow_metaproperties.py | 21 ++++++++++ secret.example.json | 9 ++++ 20 files changed, 502 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yaml rename {example => samples}/app.py (100%) create mode 100644 samples/brands.py create mode 100644 samples/campaign.py create mode 100644 samples/client.py create mode 100644 samples/collection.py rename {example => samples}/image.png (100%) create mode 100644 samples/media.py create mode 100644 samples/metaproperties.py create mode 100644 samples/pim_metaproperties.py create mode 100644 samples/tags.py create mode 100644 samples/upload_file.py create mode 100644 samples/workflow_group.py create mode 100644 samples/workflow_jobs.py create mode 100644 samples/workflow_metaproperties.py create mode 100644 secret.example.json diff --git a/.gitignore b/.gitignore index 0883b60..6acab6c 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,9 @@ ENV/ # OS generated files .DS_Store .idea/ + +# Ignore secret files +secret.json + +# Ignore volume folder created by docker +app/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b81fa00 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 +ENV PYTHONUNBUFFERED 1 + +RUN apt-get clean && apt-get update + +RUN mkdir /app +WORKDIR /app + +RUN pip install bynder-sdk + +COPY . /app/ \ No newline at end of file diff --git a/Makefile b/Makefile index 987c1e6..2b9b007 100644 --- a/Makefile +++ b/Makefile @@ -36,3 +36,16 @@ testdeps: .PHONY: typehint typehint: mypy --ignore-missing-imports --follow-imports=skip $(DISTNAME) + +# make executeSdkSample sample-file-name=metaproperties.py +.PHONY: executeSdkSample +executeSdkSample: + docker-compose exec bynder-python-sdk python /app/samples/$(sample-file-name) + +.PHONY: run-docker +run-docker: + docker-compose up -d + +.PHONY: stop-docker +stop-docker: + docker-compose down \ No newline at end of file diff --git a/README.md b/README.md index e17dba1..58c1434 100644 --- a/README.md +++ b/README.md @@ -204,3 +204,49 @@ packages required and execute the tests for all the clients. ```bash make test ``` + +Docker Setup Guide +----------------- + +The Docker setup allows you to run your Python scripts inside a Docker container, with dependencies installed and files synchronized. This guide aims to facilitate the development and testing of the SDK. + +### Requirements and dependencies + +Ensure the following are installed on your machine: + +- [Docker](https://www.docker.com/get-started/) +- [docker-compose](https://docs.docker.com/compose/) + +### Initial Setup + +Create a `secret.json` file by following the example provided in the project. Fill in the necessary settings based on your requirements. If you have a permanent token, only the domain and permanent_token fields need to be specified: + ``` + { + "domain": "example.bynder.com", # Without the http:// or https:// + "permanent_token": "7d09..........." +} + ``` + +With `docker` and `docker-compose` installed, and your `secret.json` file ready, run the following command to initiate the container: +```bash +make run-docker +``` +This command initializes a container with the bynder-python-sdk installed and ready for use. + +### Executing SDK Samples + +You can utilize the `Makefile` commands on your console to run SDK sample scripts. The syntax is as follows: +```bash +make executeSdkSample sample-file-name=file.py +``` +All sample files are located in the `./samples` directory. + +> :warning: Caution: The sample scripts are provided as examples. It is crucial to review, add and/or modify the commands before execution. The container updates automatically with changes, ensuring a seamless development experience. Always exercise caution when executing scripts. + +## Stopping the Docker Container + +When you're done with your development or testing, you can stop the Docker container using the following command: + +```bash +make stop-docker +``` diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..0527269 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,8 @@ +version: '3' +services: + bynder-python-sdk: + container_name: bynder-python-sdk + build: . + command: sh -c "tail -f /dev/null" + volumes: + - .:/app \ No newline at end of file diff --git a/example/app.py b/samples/app.py similarity index 100% rename from example/app.py rename to samples/app.py diff --git a/samples/brands.py b/samples/brands.py new file mode 100644 index 0000000..3754adb --- /dev/null +++ b/samples/brands.py @@ -0,0 +1,14 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the asset bank client +asset_bank_client = bynder_client.asset_bank_client +print('\n> Get brands:') +brands = asset_bank_client.brands() +pp.pprint(brands) diff --git a/samples/campaign.py b/samples/campaign.py new file mode 100644 index 0000000..247e7f6 --- /dev/null +++ b/samples/campaign.py @@ -0,0 +1,52 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the workflow client +workflow_client = bynder_client.workflow_client +print('\n> Get workflow users:') +workflow_users = workflow_client.users() +workflow_user = workflow_users[0]['ID'] +pp.pprint(workflow_users) + +print('\n> Create new campaign:') +new_campaign = workflow_client.create_campaign( + name='compaign_name', + key='CKEY', + description='campaign_description', + responsible_id=workflow_user +) +pp.pprint(new_campaign) + + +print('\n> Get campaigns list:') +campaigns = workflow_client.campaigns() +pp.pprint(campaigns) + + +print('\n> Get campaigns info:') +campaign_id = campaigns[0]['ID'] +campaign_info = workflow_client.campaign_info(campaign_id) +pp.pprint(campaign_info) + + +print('\n> Edit a campaign:') +edited_campaign = workflow_client.edit_campaign( + campaign_id=new_campaign['id'], + name='new_compaign_name', + key='NCKEY', + description='new_compaign_description', + responsible_id=workflow_user +) +pp.pprint(edited_campaign) + + +print('\n> Delete campaign:') +workflow_client.delete_campaign( + campaign_id=new_campaign['id'] +) \ No newline at end of file diff --git a/samples/client.py b/samples/client.py new file mode 100644 index 0000000..d18276b --- /dev/null +++ b/samples/client.py @@ -0,0 +1,48 @@ +import json + +from bynder_sdk import BynderClient + + +class BynderClientAuthentication: + + def __init__(self, config_file_path='secret.json'): + with open(config_file_path, 'r') as file: + self.config_data = json.load(file) + + def token_saver(token): + """ This function will be called by oauthlib-requests when a new + token is retrieved, either after the initial login or refreshing an + existing token. """ + print('New token received:') + print(token) + + def get_auth_client(self) -> BynderClient: + # When using Permanent Tokens + if self.config_data.get('permanent_token', None): + return BynderClient( + domain=self.config_data.get('domain', None), + permanent_token=self.config_data.get('permanent_token', None) + ) + + # When using OAuth2 + bynder_client = BynderClient( + **self.config_data, + token_saver=self.token_saver, # optional, defaults to empty lambda + ) + # Token object example + # token = { + # "access_token": "...", + # "expires_at": 123456789, + # "expires_in": 3599, + # "id_token": "...", + # "refresh_token": "...", + # "scope": ["offline"], + # "token_type": "bearer" + # } + if self.config_data.get('token', None) is None: + print(bynder_client.get_authorization_url()) + + code = input('Code: ') + print(bynder_client.fetch_token(code)) + + return bynder_client \ No newline at end of file diff --git a/samples/collection.py b/samples/collection.py new file mode 100644 index 0000000..0ec2dea --- /dev/null +++ b/samples/collection.py @@ -0,0 +1,62 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the collections client +collection_client = bynder_client.collection_client +print('\n> Create a new collection:') +new_collection = collection_client.create_collection( + name='testing collection python sdk' +) +pp.pprint(new_collection) + +print('\n> Get collections list:') +collections = collection_client.collections(query={'keyword': 'testing collection python sdk'}) +collection_id = collections[0]['id'] +pp.pprint(collections) + +print('\n> Get specific collection info:') +collection = collection_client.collection_info(collection_id) +pp.pprint(collection) + + +# Get the asset bank client to get media id +asset_bank_client = bynder_client.asset_bank_client +media_list = asset_bank_client.media_list({ + 'count': True, + 'limit': 2, + 'type': 'image', + 'versions': 1 +}) +media_id = media_list.get('media')[0].get('id') + +print('\n> Add media assets to specific collection:') +collection = collection_client.add_media_to_collection( + collection_id, + media_ids=[media_id] +) +pp.pprint(collection) + +print('\n> Get media ids of a collection:') +collection_media_ids = collection_client.collection_media_ids( + collection_id=collection_id +) +pp.pprint(collection_media_ids) + +print('\n> Remove media from specific collection:') +collection = collection_client.remove_media_from_collection( + collection_id, + media_ids=[media_id] +) +pp.pprint(collection) + +print('\n> Delete a collection:') +deleted_collection = collection_client.delete_collection( + collection_id=collection_id +) +pp.pprint(deleted_collection) diff --git a/example/image.png b/samples/image.png similarity index 100% rename from example/image.png rename to samples/image.png diff --git a/samples/media.py b/samples/media.py new file mode 100644 index 0000000..b277222 --- /dev/null +++ b/samples/media.py @@ -0,0 +1,43 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the asset bank client +asset_bank_client = bynder_client.asset_bank_client +print('\n> Get media list:') +media_list = asset_bank_client.media_list({ + 'count': True, + 'limit': 2, + 'type': 'image', + 'versions': 1 +}) +pp.pprint(media_list) + + +print('\n> Get media info:') +media_id = media_list.get('media')[0].get('id') +media_info = asset_bank_client.media_info( + media_id=media_id, + versions={ + 'versions': 1 + } +) +pp.pprint(media_info) + +print('\n Set media description:') +media = asset_bank_client.set_media_properties( + media_id, + {'description': 'Description set using SDK'} +) + +print('\n> Get download url:') +download_url = asset_bank_client.media_download_url( + media_id=media_id +) +pp.pprint(download_url) + diff --git a/samples/metaproperties.py b/samples/metaproperties.py new file mode 100644 index 0000000..28ff65c --- /dev/null +++ b/samples/metaproperties.py @@ -0,0 +1,14 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the asset bank client +asset_bank_client = bynder_client.asset_bank_client +print('\n> Get metaproperties:') +meta_properties = asset_bank_client.meta_properties() +pp.pprint(meta_properties) diff --git a/samples/pim_metaproperties.py b/samples/pim_metaproperties.py new file mode 100644 index 0000000..1f8bdc1 --- /dev/null +++ b/samples/pim_metaproperties.py @@ -0,0 +1,30 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the PIM client +pim_client = bynder_client.pim_client +print('\n> Get list of PIM metaproperties:') +pim_metaproperties = pim_client.metaproperties() +pim_metaproperty_id = pim_metaproperties[0] +pp.pprint(pim_metaproperties) + + +print('\n> Get metaproperty info:') +pim_metaproperty = pim_client.metaproperty_info( + metaproperty_id=pim_metaproperty_id +) +pp.pprint(pim_metaproperty_id) + + +print('\n> Get list of PIM metaproperty options:') +pim_metaproperty_options = pim_client.metaproperty_options( + metaproperty_id=pim_metaproperty_id +) +pim_metaproperty_option_id = pim_metaproperty_options[0]['id'] +pp.pprint(pim_metaproperty_options) diff --git a/samples/tags.py b/samples/tags.py new file mode 100644 index 0000000..c859254 --- /dev/null +++ b/samples/tags.py @@ -0,0 +1,14 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the asset bank client +asset_bank_client = bynder_client.asset_bank_client +print('\n> Get tags:') +tags = asset_bank_client.tags() +pp.pprint(tags) diff --git a/samples/upload_file.py b/samples/upload_file.py new file mode 100644 index 0000000..08be5e0 --- /dev/null +++ b/samples/upload_file.py @@ -0,0 +1,25 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the asset bank client +asset_bank_client = bynder_client.asset_bank_client +print('\n> Get brands:') +brands = asset_bank_client.brands() + +print('\n> Get brand ID:') +brand_id = brands[0]['id'] +pp.pprint(brand_id) + +print('\n> Upload a file to the asset bank') +uploaded_file = asset_bank_client.upload_file( + file_path='samples/image.png', + brand_id=brand_id +) + +pp.pprint(uploaded_file) diff --git a/samples/workflow_group.py b/samples/workflow_group.py new file mode 100644 index 0000000..4122f72 --- /dev/null +++ b/samples/workflow_group.py @@ -0,0 +1,22 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the workflow client +workflow_client = bynder_client.workflow_client +print('\n> Get workflow groups list:') +workflow_groups = workflow_client.groups() +workflow_group_id = workflow_groups[0]['ID'] +pp.pprint(workflow_groups) + + +print('\n> Get workflow group info:') +workflow_group = workflow_client.group_info( + group_id=workflow_group_id +) +pp.pprint(workflow_group) diff --git a/samples/workflow_jobs.py b/samples/workflow_jobs.py new file mode 100644 index 0000000..0285557 --- /dev/null +++ b/samples/workflow_jobs.py @@ -0,0 +1,64 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the workflow client +workflow_client = bynder_client.workflow_client +print('\n> Get campaigns list:') +campaigns = workflow_client.campaigns() + +print('\n> Get campaign ID:') +campaign_id = campaigns[0]['ID'] +pp.pprint(campaign_id) + +print('\n> Get jobs:') +jobs = workflow_client.jobs() +job_id = jobs[0]['id'] +pp.pprint(jobs) + +print('\n> Get jobs by campaign:') +jobs_by_campaign = workflow_client.jobs( + campaign_id=campaign_id +) +pp.pprint(jobs_by_campaign) + +print('\n> Get specific job:') +job_info = workflow_client.job_info( + job_id=job_id +) +pp.pprint(job_info) + +print('\n> Create new job:') +new_job = workflow_client.create_job( + name='new_job_name', + campaign_id=job_info['campaignID'], + accountable_id=job_info['accountableID'], + preset_id=job_info['presetID'] +) +pp.pprint(new_job) + +print('\n> Edit job:') +edited_job = workflow_client.edit_job( + job_id, + name='edited_job_name', + campaign_id=job_info['campaignID'], + accountable_id=job_info['accountableID'], + preset_id=job_info['presetID'] +) +pp.pprint(edited_job) + +print('\n> Delete job:') +workflow_client.delete_job( + job_id=job_id +) + +print('\n> Get job preset info:') +job_preset_info = workflow_client.job_preset_info( + job_preset_id=job_info['presetID'] +) +pp.pprint(job_preset_info) diff --git a/samples/workflow_metaproperties.py b/samples/workflow_metaproperties.py new file mode 100644 index 0000000..5b12894 --- /dev/null +++ b/samples/workflow_metaproperties.py @@ -0,0 +1,21 @@ +import pprint + +from client import BynderClientAuthentication + +pp = pprint.PrettyPrinter() + +auth_instance = BynderClientAuthentication() +bynder_client = auth_instance.get_auth_client() + +# Get the workflow client +workflow_client = bynder_client.workflow_client +print('\n> Get workflow metaproperties list:') +workflow_metaproperties = workflow_client.metaproperties() +workflow_metaproperty_id = workflow_metaproperties[0]['ID'] +pp.pprint(workflow_metaproperties) + + +print('\n> Get workflow metaproperty info:') +workflow_metaproperty = workflow_client.metaproperty_info( + metaproperty_id=workflow_metaproperty_id) +pp.pprint(workflow_metaproperty) diff --git a/secret.example.json b/secret.example.json new file mode 100644 index 0000000..e51bfa9 --- /dev/null +++ b/secret.example.json @@ -0,0 +1,9 @@ +{ + "domain": "example.bynder.com without the http:// or https://", + "redirect_uri": "url where user will be redirected after authenticating", + "client_id": "your OAuth app client id", + "client_secret": "your OAuth app client secret", + "scopes": ["offline", "asset:read", "meta.assetbank:read"], + "token": "token json object check samples/client.py comment for example (not required EXCEPT if you're running on docker)", + "permanent_token": "permanent token hash generated on platform" +}