Библиотека python для использования API Yandex connect / Яндекс коннект.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

203 lines
5.7 KiB

# coding: utf8
"""
Yandex.Connect Base API module
:author: Alexeev Nick
:email: n@akolka.ru
:version: 0.01b
"""
import json
import requests
import datetime
import inspect
def json_prepare_dump(obj):
"""
Подготовка к json.dumps
:param obj: объект
:return: подготовленный объект
"""
if isinstance(obj, list):
for i, item in enumerate(obj):
obj[i] = json_prepare_dump(item)
elif isinstance(obj, dict):
for key in obj:
obj[key] = json_prepare_dump(obj[key])
elif type(obj) is datetime.date:
return obj.isoformat()
elif isinstance(obj, datetime.datetime):
return obj.isoformat()
return obj
def inspect_args_func(frame):
"""
Inspect current def arguments
:param frame: inspect.currentframe()
:return: dict
"""
args, _, _, values = inspect.getargvalues(frame)
return {key: values[key] for key in args if key != 'self'}
class YandexConnectException(Exception):
"""
Exception of module
"""
pass
class YandexConnectExceptionY(Exception):
"""
Exception by yandex request
"""
pass
class YandexConnectRequest(object):
""" Yandex Connect request API object """
_version = None # API version
_oauth_token = None # OAuth Token
_org_id = None # Org ID
_domain = None # Domain
def __init__(self, domain, oauth_token, org_id=None, version=6):
"""
Init
:param domain: yandex domain
:param oauth_token: OAuth Token — https://oauth.yandex.ru/
:param org_id: Organization id
:param version: API version
"""
self._domain = domain
self._oauth_token = oauth_token
self._org_id = org_id
if version:
self._version = version
def __call__(self, name, data=None, method='post'):
"""
Base request method
:param name: url path
:param data: data / args of request
:param method: request method - get/post
:raise YandexConnectException: bad request, jsonify failed
:raise YandexConnectExceptionY: yandex exception
:return: dict
"""
url = '%(domain)s/v%(version)s/%(name)s' % {
'domain': self._domain,
'version': self._version,
'name': name
}
if not url.endswith('/'):
url = '%s/' % url
if data:
for key in data.keys():
if data[key] is None or (isinstance(data[key], dict) and not data[key]):
del data[key]
continue
method = method.lower()
if method not in ['get', 'post', 'patch', 'delete']:
raise ValueError('Not right method')
kwargs = {
'headers': {
'Authorization': 'OAuth %s' % self._oauth_token,
'X-Org-ID': self._org_id if self._org_id else None
}
}
if method in ['post', 'patch']:
if data:
module = name.split('/')[0]
if module.endswith('s'):
module = module[:-1]
key_id = '%s_id' % module
if key_id in data:
del data[key_id]
kwargs['data'] = json.dumps(json_prepare_dump(data))
kwargs['headers']['Content-Type'] = 'application/json'
else:
kwargs['params'] = data
if not kwargs['headers']['X-Org-ID']:
del kwargs['headers']['X-Org-ID']
try:
r = getattr(requests, method)(url, **kwargs)
except Exception:
raise YandexConnectException(u'Request error: send', name, data)
if r.status_code > 299:
try:
msg = r.json()
except Exception:
msg = r.text
raise YandexConnectExceptionY(r.status_code, msg)
if method == 'delete':
return True
try:
ret = r.json()
except Exception:
return True
return ret
class YandexConnectBase(object):
""" Yandex connect API base class"""
DOMAIN = None # Request Domain
request = None # Request object
def __init__(self, oauth_token, org_id=None, version=6):
"""
:param oauth_token: OAuth token
:param org_id: ID org
:param version: API version
"""
self.request = YandexConnectRequest(self.DOMAIN, oauth_token, org_id=org_id, version=version)
@staticmethod
def prepare_fields(fields, title_field, only_title_field=False):
"""
Prepare fields data key
:param fields: obj
:param title_field: second field
:param only_title_field: return only title field
:return:
"""
if not fields:
if not only_title_field:
fields = ['id', title_field]
else:
fields = [title_field]
if isinstance(fields, list):
fields = u','.join(fields)
return fields
def list_full(self, callback, default_field, **kwargs):
"""
List full
:param callback: callback function
:param default_field: default field
:param kwargs: params
:return: list
"""
kwargs['fields'] = self.prepare_fields(kwargs['fields'], default_field)
kwargs['per_page'] = 100
pages = None
page = 1
ret = []
while True:
kwargs['page'] = page
r = callback(**kwargs)
if pages is None:
pages = r['pages']
ret += r['result']
if page >= pages:
break
page += 1
return ret