GithubHelp home page GithubHelp logo

bynder / bynder-python-sdk Goto Github PK

View Code? Open in Web Editor NEW
8.0 61.0 11.0 141 KB

SDK in Python for integration with Bynder

License: MIT License

Makefile 1.95% Python 97.76% Dockerfile 0.29%
integration sdk python api

bynder-python-sdk's Introduction

Bynder Python SDK

Tests Publish Coverage Status PyPI PyPI - Downloads

The main goal of this SDK is to speed up the integration of Bynder customers who use Python. Making it easier to connect to the Bynder API (https://bynder.docs.apiary.io) and execute requests on it.

Note: As of version 1.0.0 this SDK now uses OAuth 2.0. For the last version using OAuth 1.0a please refer to version 0.0.6.

Requirements and dependencies

The Python SDK requires the following in order to fully work:

  • Python >= 3.5, older versions of Python won't work.

Pip should handle all the dependencies automatically.

Installation

This SDK depends on a few libraries in order to work, installing it with pip should take care of everything automatically.

Before you install the SDK we recommend you to setup a virtual environment:

virtualenv -p python3 venv  # create virtual environment
source venv/bin/activate    # activate virtual environment

After you have successfully setup a virtual environment you can install the SDK with pip. Run the following command while your virtual environment is active.

pip install bynder-sdk

Getting started

This is a simple example on how to retrieve data from the Bynder asset bank. For a more detailed example of implementation refer to the sample code.

First import the BynderClient:

from bynder_sdk import BynderClient

When using OAuth2, create an instance of the client and use the flow to receive a token:

bynder_client = BynderClient(
    domain='portal.getbynder.com',
    redirect_uri='https://...',
    client_id='',
    client_secret='',
    token_saver=token_saver
)

print(bynder_client.get_authorization_url())
code = input('Code: ')
bynder_client.fetch_token(code)

When using a permanent token, the client instance can be created like this:

bynder_client = BynderClient(
  domain='portal.getbynder.com',
  permanent_token=''
)

Finally call one of the API's endpoints through one of the clients:

asset_bank_client = bynder_client.asset_bank_client
media_list = asset_bank_client.media_list({
    'limit': 2,
    'type': 'image'
})

A full list of the currently available clients and methods in the SDK can be found below

Methods Available

These are the methods currently availble on the Bynder Python SDK, refer to the Bynder API Docs for more specific details on the calls.

BynderClient:

Get an instance of the Asset Bank Client or the Collection Client if already with access tokens set up. Also allows to generate and authenticate request tokens, which are necessary for the rest of the Asset Bank and Collection calls.

asset_bank_client
collection_client
pim_client
workflow_client
get_authorization_url()
fetch_token()
derivatives()

asset_bank_client:

All the Asset Bank related calls, provides information and access to Media management.

brands()
tags()
meta_properties()
media_list(query)
media_info(media_id, query)
media_download_url()
set_media_properties(media_id, query)
delete_media(media_id)
create_usage(itegration_id, asset_id, query)
usage(query)
delete_usage(integration_id, asset_id, query)
upload_file(file_path, brand_id, media_id, query)

With the upload_file method you can do two things. You can upload a new asset, or you can upload a new version of an exising asset. You can control this by sending a media_id or not.

collection_client:

All the collection related calls.

collections(query)
collection_info(collection_id)
create_collection(name, query)
delete_collection(collection_id)
collection_media_ids(collection_id)
add_media_to_collection(collection_id, media_ids)
remove_media_from_collection(collection_id, meedia_ids)
share_collection(collection_id, collection_option, recipients, query)

pim_client:

All the PIM related calls.

metaproperties()
metaproperty_info(metaproperty_id)
metaproperty_options(metaproperty_id)
edit_metaproperty_option(metaproperty_option_id, children)

workflow_client:

All the workflow related calls.

users()
campaigns(query)
campaign_info(campaign_id)
create_campaign(name, key, description, responsibleID, query)
delete_campaign(campaign_id)
edit_campaign(campaign_id, name, key, description, responsibleID, query)
metaproperties()
metaproperty_info(metaproperty_id)
groups()
group_info(group_id)
job_preset_info(job_preset_info)
jobs(campaign_id)
create_job(name, campaignID, accountableID, presetID, query)
job_info(job_id)
edit_job(job_id, name, campaignID, accauntableID, presetID, query)
delete_job(job_id)}

Tests

You can run the tests by using the command below. This will install the packages required and execute the tests for all the clients.

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:

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:

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:

make executeSdkSample sample-file-name=file.py

All sample files are located in the ./samples directory.

โš ๏ธ 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:

make stop-docker

bynder-python-sdk's People

Contributors

agsimmons avatar ahongbynder avatar arpit-sharma-usc avatar betacar avatar danielsequeira avatar dylanmartins avatar fnavarrogonzalez avatar martensies avatar stefanpelders avatar vladox avatar woutertoering avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bynder-python-sdk's Issues

Unable to authenticate using Client Credentials

I have setup my oauth2 application in Bynder to authenticate using Client Credentials.
I can authenticate using postman by calling the /token endpoint.

When connecting using the python sdk, it looks like the client credential flow is not implemented correctly.
The OAuth2Session will default to a WebApplicationClient where a BackendApplicationClient would be needed for client credential authentication.

In my current workaround im fetching the token up front, but it would be nice if the sdk could handle oauth2 authentication using client credentials

client = BackendApplicationClient(client_id='<clientId>')
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url='<tokenurl>', client_id='<clientId>',client_secret='<clientSecret>')

bynder_client = BynderClient(
    domain='<bynderDomain>',
    redirect_uri='', #required but should not be used
    token = token, #input the token to avoid the bynder client trying to fetch
    client_id='<clientId>', #Not used since the token is supplied
    client_secret='<clientSecret>',#Not used since the token is supplied
    scopes=['<scope>','<scope>']
)

Upload file to the asset bank gives an error related to the Bad Request for url

Using the code in the example app.py to upload a small png to the asset bank:

def uploadFile(asset_bank_client, brand_id, file_path):
    print('\n> Upload a file to the asset bank')
    uploaded_file = asset_bank_client.upload_file(
    file_path=file_path,
    brand_id=brand_id)
    print(uploaded_file)

Gives out this error:

Traceback (most recent call last):
  File "e:\Dev\Bynder-test\main.py", line 100, in <module>
    uploadFile(asset_bank_client, 'AAAAAAA-AAAA-AAAA-AAAAAAAAAAAAAA', 'E:\\Dev\\Bynder-test\\test.png')
  File "e:\Dev\Bynder-test\main.py", line 63, in uploadFile
    uploaded_file = asset_bank_client.upload_file(
  File "E:\Dev\Bynder-test\venv\lib\site-packages\bynder_sdk\client\asset_bank_client.py", line 104, in upload_file 
    return self.upload_client.upload(
  File "E:\Dev\Bynder-test\venv\lib\site-packages\bynder_sdk\client\upload_client.py", line 21, in upload
    init_data, total_parts = self._run_s3_upload(file_path)
  File "E:\Dev\Bynder-test\venv\lib\site-packages\bynder_sdk\client\upload_client.py", line 47, in _run_s3_upload   
    response.raise_for_status()
  File "E:\Dev\Bynder-test\venv\lib\site-packages\requests\models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://bynder-public-eu-central-1.s3.amazonaws.com/

Brand Id replaced in the error.

Seems like something in the SDK methods?

Unable to import `bynder_sdk.BynderClient` in version 1.1.3

After installing latest via pip install bynder-sdk:

>>> from bynder_sdk import BynderClient
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/dev/Desktop/internal-tools/dashboard/venv/lib/python3.7/site-packages/bynder_sdk/__init__.py", line 1, in <module>
    from bynder_sdk.client.bynder_client import BynderClient # noqa
  File "/Users/dev/Desktop/internal-tools/dashboard/venv/lib/python3.7/site-packages/bynder_sdk/client/bynder_client.py", line 6, in <module>
    from bynder_sdk.oauth2 import BynderOAuth2Session
  File "/Users/dev/Desktop/internal-tools/dashboard/venv/lib/python3.7/site-packages/bynder_sdk/oauth2.py", line 6, in <module>
    from bynder_sdk.util import SessionMixin
  File "/Users/dev/Desktop/internal-tools/dashboard/venv/lib/python3.7/site-packages/bynder_sdk/util.py", line 1, in <module>
    with open('VERSION') as fh:
FileNotFoundError: [Errno 2] No such file or directory: 'VERSION'

To resolve this issue, I downgraded to version 1.1.2 and I was able to import BynderClient and successfully make API calls.

400 Client Error: Bad request

I suspect that this is related to #33 but I wanted to ask.

I am extending the AssetBankClient to create metaproperty option (as mentioned in #30):

    def create_metaproperty_option(self, property_id, query: dict = None):
        """ Creates a new meta property option. """    
        return self.session.post(f'/v4/metaproperties/{property_id}/options', data=query or {})

Using OAuth2 permanent access token, I'm getting an error triggered from the util.py post function,

raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://<myclienturl>.bynder.com/api/v4/metaproperties/3508BEA1-6255-4225-82D14EBC652BE240/options

Is this the same issue, or different?

[edit: I'm actually using a permanent token with full read/write permissions for Assets, Collections, Metaproperties, and Analytics]

Error modifying asset properties

Calling

asset_bank_client.set_media_properties('715AB17A-AE69-4B40-AFA7C1295A874B89', {'metaproperty.1389E77E-F6A1-4698-95DC07D30C6E1683': '8E92E068-E335-425C-805D16E8D04026AA'})

Results in:

"/Users/christopherlunt/.pyenv/versions/imageaudit/lib/python3.7/site-packages/bynder_sdk/client/asset_bank_client.py", line 53, in set_media_properties
    payload=query or {}
  File "/Users/christopherlunt/.pyenv/versions/imageaudit/lib/python3.7/site-packages/bynder_sdk/util.py", line 27, in post
    return self.wrapped_request(super().post, url, *args, **kwargs)
  File "/Users/christopherlunt/.pyenv/versions/imageaudit/lib/python3.7/site-packages/bynder_sdk/util.py", line 16, in wrapped_request
    response = func(endpoint, *args, **kwargs)
  File "/Users/christopherlunt/.pyenv/versions/imageaudit/lib/python3.7/site-packages/requests/sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
TypeError: request() got an unexpected keyword argument 'payload'

I can't seem to modify any properties, even calling with an empty query causes an error.

HTTPError: 403 Client Error: Forbidden for url

Hi,
I'm getting an "HTTPError: 403 Client Error: Forbidden for url: " error when I try to run the following with the SDK (I've hidden the token and the domain, obviously). This worked previously. I can sign-in as normal -- so the server is working. When I click on the that is returned in the error message that works, too (because I'm authenticated).

The returned url is my-domain/api/v4/metaproperties in this example.

I had the admin look at the token, and permissions still seem OK. Ideas?
Ted

from bynder_sdk import BynderClient
#PERMTOKEN='permanent_token'

bynder_client = BynderClient(
  domain='my-domain',
  permanent_token=PERMTOKEN
)

asset_bank_client = bynder_client.asset_bank_client

mp=asset_bank_client.meta_properties()

athentication-refresh token access with SDK

Trying to access our Bynder instance with the python SDK. I've tried the "getting started" and running into problems.

I've submitted a ticket 160448 and they redirected me here.

from bynder_sdk import BynderClient

bynder_client = BynderClient(
    domain=DOMAIN,
    redirect_uri='https://localhost/callback',
    client_id=CLIENTID,
    client_secret=CLIENTSECRET
)

print(bynder_client.get_authorization_url())
code = input('Code: ')
bynder_client.fetch_token(code)

asset_bank_client = bynder_client.asset_bank_client
media_list = asset_bank_client.media_list({
    'limit': 2,
    'type': 'image'
})


# ERROR
# TypeError: Missing required arguments: ['scopes']
# 
# %%
bynder_client = BynderClient(
    domain=DOMAIN,
    redirect_uri='https://localhost/callback',
    client_id=CLIENTID,
    client_secret=CLIENTSECRET,
    scopes=['offline',
            'asset:read',
            'meta.assetbank:read'],
)

print(bynder_client.get_authorization_url())
code = input('Code: ')
bynder_client.fetch_token(code)

asset_bank_client = bynder_client.asset_bank_client
media_list = asset_bank_client.media_list({
    'limit': 2,
    'type': 'image'
})

# RESPONSE:
#    ('https://https://[MYDOMAIN]/v6/authentication/
#      oauth2/auth?response_type=code&client_id=[MYCLIENTID]&
#      redirect_uri=https%3A%2F%2Flocalhost%2Fcallback.&scope=offline+asset%3Aread+
#      meta.assetbank%3Aread&state=ElNUPvMv', 'ElNUPvMv')
#
# ENTERED CODE from state above...
#    Code: ElNUPvMv
#
# ConnectionError: HTTPSConnectionPool(host='https', port=443): Max retries 
# exceeded with url: //[MYDOMAIN]/v6/authentication/oauth2/token 
# (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] 
# getaddrinfo failed'))

Responsible ID not part of response for active stage of workflow campaign

We would like to get the responsible of a job at a certain active stage. However that doesn't seem to be possible, as by using the SDK function to get the job information:

job_info = workflow_client.job_info(
    job_id=id
)
pp.pprint(job_info)

We get back a response that looks like this:

{
....,
    "job_previous_stage": null,
    "job_active_stage": {
        "id": "841ed69a-3b14-4c06-ab87-7d97a082700a",
        "status": "Active",
        "position": 1.0
    },
    "job_next_stage": {
        "id": "9442b38f-7f47-48ce-a04b-037a6b29c99a",
        "status": "Idle",
        "position": 2.0,
        "responsibleID": null,
        "responsibleGroupID": null
    },
    "job_stages": [
        {
            "id": "841ed69a-3b14-4c06-ab87-7d97a082700a",
            "status": "Active",
            "position": 1.0
        },
        {
            "id": "9442b38f-7f47-48ce-a04b-037a6b29c99a",
            "status": "Idle",
            "position": 2.0
        },
        {
            "id": "1a57e079-770f-41e1-8686-763526a0174e",
            "status": "Idle",
            "position": 3.0
        }
    ]
....

As you can see it is only possible to get the ID of the responsible for the next stage. Is there a way to get the ID of the responsible of the current stage? So far we haven't found another way.

Error retrieving derivatives

When using the SDK to retrieve the derivatives of an account,
`
from bynder_sdk import BynderClient
import configparser

config = configparser.ConfigParser()
config.read('bynder.ini')

bynder_client = BynderClient(
base_url=config.get('BYNDER_TOKENS', 'base_url'),
consumer_key=config.get('BYNDER_TOKENS', 'consumer_key'),
consumer_secret=config.get('BYNDER_TOKENS', 'consumer_secret'),
token=config.get('BYNDER_TOKENS', 'token'),
token_secret=config.get('BYNDER_TOKENS', 'token_secret')
)

print(bynder_client.derivatives())
`

it throws an exception:
Traceback (most recent call last): File "/Users/makra/Library/Mobile Documents/com~apple~CloudDocs/S&V/UnitD/Eurobike/Byndertest/main.py", line 19, in <module> print(bynder_client.derivatives()) File "/Users/makra/Byndertest/lib/python3.6/site-packages/bynder_sdk/client/bynder_client.py", line 116, in derivatives endpoint='/api/v4/derivatives/' File "/Users/makra/Byndertest/lib/python3.6/site-packages/bynder_sdk/oauth/oauth_request_handler.py", line 62, in get params=params File "/Users/makra/Byndertest/lib/python3.6/site-packages/bynder_sdk/oauth/oauth_request_handler.py", line 50, in _generic_request response.raise_for_status() File "/Users/makra/Byndertest/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://your-bynder-domain/api/v4/derivatives/

If i open the API endpoint like it is specified in the documentation:
https://your-bynder-domain/api/v4/account/derivatives/
everything works and show the correct information. Please note the differences in the path between API and SDK.
In bynder_client.px line 116 the line should be changed to:
endpoint='/api/v4/account/derivatives/'

Connection error

Problem with connecting. Is this the right way to use code? From the response? Why is connection failing?
Ref: Issue #31.

bynder_client = BynderClient(
    domain=DOMAIN,
    redirect_uri='https://localhost/callback',
    client_id=CLIENTID,
    client_secret=CLIENTSECRET,
    scopes=['offline',
            'asset:read',
            'meta.assetbank:read'],
)

print(bynder_client.get_authorization_url())
code = input('Code: ')
bynder_client.fetch_token(code)

asset_bank_client = bynder_client.asset_bank_client
media_list = asset_bank_client.media_list({
    'limit': 2,
    'type': 'image'
})

# RESPONSE:
#    ('https://https://[MYDOMAIN]/v6/authentication/
#      oauth2/auth?response_type=code&client_id=[MYCLIENTID]&
#      redirect_uri=https%3A%2F%2Flocalhost%2Fcallback.&scope=offline+asset%3Aread+
#      meta.assetbank%3Aread&state=ElNUPvMv', 'ElNUPvMv')
#
# ENTERED CODE from state above...
#    Code: ElNUPvMv
#
# ConnectionError: HTTPSConnectionPool(host='https', port=443): Max retries 
# exceeded with url: //[MYDOMAIN]/v6/authentication/oauth2/token 
# (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 11001] 
# getaddrinfo failed'))

Allow configuration of connection pool size for BynderClient

Currently, there is no way to increase the max number of connection pool used by the SDK.

The connection pool is created by: https://github.com/psf/requests/blob/99b3b492418d0751ca960178d274f89805095e4c/requests/adapters.py#L114 (BynderOAuth2Session --> requests_oauthlib.oauth2_session.OAuth2Session --> requests.Session --> requests.adapter) which the default is set to 10 connections.

It would be advantageous to abstract the configuration of that value to the SDK, so that bulk image uploads can be processed in a timely fashion.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.