Skip to content
Draft
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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ unittest:
nosetests -v --stop


gen_classes:
cd tools && ./gen_classes.py --spec-path ../specification --doc-json doc_dict.json -o ../zenpy/lib/
8 changes: 8 additions & 0 deletions specification/zendesk/attribute_value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"attribute_id": "9b660de4-72d1-11eb-814d-d9d87f5c2ded",
"created_at": "2021-02-19T16:43:38Z",
"id": "9d80ff0a-72d1-11eb-95e0-f5b65d6795d8",
"name": "Finance",
"updated_at": "2021-02-19T20:01:08Z",
"url": "https://pdi-testboxlab.zendesk.com/api/v2/routing/attributes/9b660de4-72d1-11eb-814d-d9d87f5c2ded/values/9d80ff0a-72d1-11eb-95e0-f5b65d6795d8.json"
}
7 changes: 7 additions & 0 deletions specification/zendesk/routing_attribute.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"url": "https://facetoe1.zendesk.com/api/v2/routing/attributes/15821cba-7326-11e8-b07e-950ba849aa27.json",
"created_at": "2017-12-01T19:29:31Z",
"updated_at": "2017-12-01T19:29:31Z",
"id": "15821cba-7326-11e8-b07e-950ba849aa27",
"name": "Language"
}
7 changes: 7 additions & 0 deletions specification/zendesk/routing_attribute_value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"url": "https://facetoe1.zendesk.com/api/v2/routing/attributes/15821cba-7326-11e8-b07e-950ba849aa27.json",
"created_at": "2017-12-01T19:29:31Z",
"updated_at": "2017-12-01T19:29:31Z",
"id": "b376b35a-e38b-11e8-a292-e3b6377c5575",
"name": "French"
}
12 changes: 12 additions & 0 deletions tests/test_api/test_routing_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from zenpy.lib.api_objects import RoutingAttribute
from test_api.fixtures import SingleCreateApiTestCase
from zenpy.lib.exception import ZenpyException

# https://developer.zendesk.com/rest_api/docs/support/skill_based_routing

class TestRoutingApi(SingleCreateApiTestCase):
__test__ = True
ZenpyType = RoutingAttribute
object_kwargs = dict(name='test_attribute')
api_name = 'routing.attributes'

23 changes: 12 additions & 11 deletions tools/gen_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,15 @@ def process_specification_directory(glob_pattern, outfile_name, namespace, write

out_file.write("\n\n\n".join((header, formatted_code)))

process_specification_directory('zendesk/*.json', 'api_objects/__init__.py',
namespace='core')
process_specification_directory('chat/*.json', 'api_objects/chat_objects.py',
namespace='chat',
write_baseclass=False)
process_specification_directory('help_centre/*.json', 'api_objects/help_centre_objects.py',
namespace='help_center',
write_baseclass=False)
process_specification_directory('talk/*.json', 'api_objects/talk_objects.py',
namespace='core',
write_baseclass=False)
if __name__ == '__main__':
process_specification_directory('zendesk/*.json', 'api_objects/__init__.py',
namespace='core')
process_specification_directory('chat/*.json', 'api_objects/chat_objects.py',
namespace='chat',
write_baseclass=False)
process_specification_directory('help_centre/*.json', 'api_objects/help_centre_objects.py',
namespace='help_center',
write_baseclass=False)
process_specification_directory('talk/*.json', 'api_objects/talk_objects.py',
namespace='core',
write_baseclass=False)
2 changes: 2 additions & 0 deletions zenpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
CustomAgentRolesApi,
SearchApi,
UserFieldsApi,
RoutingApi
)

from zenpy.lib.cache import ZenpyCache, ZenpyCacheManager
Expand Down Expand Up @@ -162,6 +163,7 @@ def __init__(
self.custom_agent_roles = CustomAgentRolesApi(
config, object_type="custom_agent_role"
)
self.routing = RoutingApi(config)

@staticmethod
def http_adapter_kwargs():
Expand Down
97 changes: 93 additions & 4 deletions zenpy/lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def __init__(self, subdomain, session, timeout, ratelimit,
CombinationResponseHandler,
ViewResponseHandler,
SlaPolicyResponseHandler,
RoutingResponseHandler,
RequestCommentResponseHandler,
GenericZendeskResponseHandler,
HTTPOKResponseHandler,
Expand Down Expand Up @@ -122,7 +123,12 @@ def _call_api(self, http_method, url, **kwargs):
:param kwargs: Any additional kwargs to pass on to requests.
"""
log.debug("{}: {} - {}".format(http_method.__name__.upper(), url,

kwargs))

if 'raw_response' in kwargs:
kwargs.pop('raw_response', None)

if self.ratelimit is not None:
# This path indicates we're taking a proactive approach to not hit the rate limit
response = self._ratelimit(http_method=http_method,
Expand All @@ -147,6 +153,9 @@ def _call_api(self, http_method, url, **kwargs):
sleep(1)
response = http_method(url, **kwargs)

#if '.post' in str(http_method):
# import epdb; epdb.st()

self._check_response(response)
self._update_callsafety(response)
return response
Expand Down Expand Up @@ -239,8 +248,7 @@ def _serialize(self, zenpy_object):
return json.loads(
json.dumps(zenpy_object, default=json_encode_for_zendesk))

def _query_zendesk(self, endpoint, object_type, *endpoint_args,
**endpoint_kwargs):
def _query_zendesk(self, endpoint, object_type, *endpoint_args, **endpoint_kwargs):
"""
Query Zendesk for items. If an id or list of ids are passed, attempt to locate these items
in the relevant cache. If they cannot be found, or no ids are passed, execute a call to Zendesk
Expand All @@ -254,6 +262,9 @@ def _query_zendesk(self, endpoint, object_type, *endpoint_args,
:return: either a ResultGenerator or a Zenpy object.
"""

#if 'value' in str(object_type):
# import epdb; epdb.st()

_id = endpoint_kwargs.get('id', None)
if _id:
item = self.cache.get(object_type, _id)
Expand All @@ -278,6 +289,10 @@ def _query_zendesk(self, endpoint, object_type, *endpoint_args,
response_objects=cached_objects,
object_type=object_type)
else:

#if 'value' in str(object_type):
# import epdb; epdb.st()

return self._get(
self._build_url(
endpoint=endpoint(*endpoint_args, **endpoint_kwargs)))
Expand Down Expand Up @@ -346,8 +361,7 @@ def __init__(self, config, object_type, endpoint=None):
self._object_mapping = ZendeskObjectMapping(self)

def __call__(self, *args, **kwargs):
return self._query_zendesk(self.endpoint, self.object_type, *args,
**kwargs)
return self._query_zendesk(self.endpoint, self.object_type, *args, **kwargs)

def _get_user(self, user_id):
if int(user_id) < 0:
Expand Down Expand Up @@ -428,6 +442,11 @@ def _get_view(self, view_id):
'view',
id=view_id)

def _get_routing_attribute(self, attribute_id):
return self._query_zendesk(EndpointFactory('attributes'),
'attribute',
id=attribute_id)

def _get_topic(self, forum_topic_id):
return self._query_zendesk(EndpointFactory('help_centre').topics,
'topic',
Expand Down Expand Up @@ -1831,6 +1850,76 @@ def make_default(self, user, group_membership):
payload={})


class RoutingAttributeValueApi(CRUDApi):

# defines the top level key for REST payloads
object_type = 'attribute_value'

# values are children of attributes, so an attribute must be passed
# to the constructor ...
def __init__(self, config, attribute=None):
super(RoutingAttributeValueApi, self).__init__(config, object_type=self.object_type)


class RoutingAttributeDefinitionApi(CRUDApi):

# defines the top level key for REST payloads
object_type = 'definition'

# values are children of attributes, so an attribute must be passed
# to the constructor ...
def __init__(self, config, attribute=None):
print(f'# ATTRIBUTE {attribute}')
super(RoutingAttributeDefinitionApi, self).__init__(config, object_type=self.object_type)


class RoutingAttributeApi(CRUDApi):

# defines the top level key for REST payloads
object_type = 'attribute'

def __init__(self, config):
super(RoutingAttributeApi, self).__init__(config, object_type=self.object_type)
self.values = RoutingAttributeValueApi(config)
self.definitions = RoutingAttributeDefinitionApi(config)


class RoutingAgentInstanceValuesApi(CRUDApi):
# defines the top level key for REST payloads
object_type = 'attribute_value_ids'

def __init__(self, config):
super(RoutingAgentInstanceValuesApi, self).__init__(config, object_type=self.object_type)

def create(self, attribute_value_ids, id=None):
# bypass default crudrequest post so we can have
# direct control over payload creation ...
cr = CRUDRequest(self)
endpoint = cr.api.endpoint
url = cr.api._build_url(endpoint(id=id))
payload = {
'attribute_value_ids': [x.id for x in attribute_value_ids]
}
return cr.api._post(url, payload)


class RoutingAgentApi(CRUDApi):

# defines the top level key for REST payloads
object_type = 'agent'

def __init__(self, config):
super(RoutingAgentApi, self).__init__(config, object_type=self.object_type)
self.instance_values = RoutingAgentInstanceValuesApi(config)


class RoutingApi(CRUDApi):
def __init__(self, config):
super(RoutingApi, self).__init__(config, object_type='routing')
self.attributes = RoutingAttributeApi(config)
self.agents = RoutingAgentApi(config)


class JiraLinkApi(CRUDApi):
def __init__(self, config):
super(JiraLinkApi, self).__init__(config, object_type='link')
Expand Down
Loading