From 7f0709b65c4c28dd8073f859a2a746e94d5ab043 Mon Sep 17 00:00:00 2001 From: Daw-Ran Liou Date: Sun, 5 Jun 2016 14:03:26 -0700 Subject: [PATCH] Annotate zerver.views.webhooks.freshdesk Change the comments into docstrings. Modified the return type of parse_freshdesk_event to always return a list of str. --- zerver/views/webhooks/freshdesk.py | 55 +++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/zerver/views/webhooks/freshdesk.py b/zerver/views/webhooks/freshdesk.py index 513a803c66..9b4c6b762f 100644 --- a/zerver/views/webhooks/freshdesk.py +++ b/zerver/views/webhooks/freshdesk.py @@ -1,9 +1,10 @@ -# Webhooks for external integrations. +"""Webhooks for external integrations.""" from __future__ import absolute_import +from django.http import HttpRequest, HttpResponse from django.utils.translation import ugettext as _ -from zerver.models import get_client +from zerver.models import get_client, UserProfile from zerver.lib.actions import check_send_message from zerver.lib.response import json_success, json_error from zerver.lib.notifications import convert_html_to_markdown @@ -12,24 +13,32 @@ from zerver.decorator import REQ, has_request_variables, authenticated_rest_api_ import logging import ujson +from six import text_type +from typing import Any, Dict, Optional, Tuple, Union + class TicketDict(dict): """ A helper class to turn a dictionary with ticket information into an object where each of the keys is an attribute for easy access. """ + def __getattr__(self, field): + # type: (str) -> Any if "_" in field: return self.get(field) else: return self.get("ticket_" + field) + def property_name(property, index): - # The Freshdesk API is currently pretty broken: statuses are customizable - # but the API will only tell you the number associated with the status, not - # the name. While we engage the Freshdesk developers about exposing this - # information through the API, since only FlightCar uses this integration, - # hardcode their statuses. + # type: (str, int) -> str + """The Freshdesk API is currently pretty broken: statuses are customizable + but the API will only tell you the number associated with the status, not + the name. While we engage the Freshdesk developers about exposing this + information through the API, since only FlightCar uses this integration, + hardcode their statuses. + """ statuses = ["", "", "Open", "Pending", "Resolved", "Closed", "Waiting on Customer", "Job Application", "Monthly"] priorities = ["", "Low", "Medium", "High", "Urgent"] @@ -41,10 +50,13 @@ def property_name(property, index): else: raise ValueError("Unknown property") + def parse_freshdesk_event(event_string): - # These are always of the form "{ticket_action:created}" or - # "{status:{from:4,to:6}}". Note the lack of string quoting: this isn't - # valid JSON so we have to parse it ourselves. + # type: (str) -> List[str] + """These are always of the form "{ticket_action:created}" or + "{status:{from:4,to:6}}". Note the lack of string quoting: this isn't + valid JSON so we have to parse it ourselves. + """ data = event_string.replace("{", "").replace("}", "").replace(",", ":").split(":") if len(data) == 2: @@ -55,11 +67,13 @@ def parse_freshdesk_event(event_string): # This is a property change event, like {status:{from:4,to:6}}. Pull out # the property, from, and to states. property, _, from_state, _, to_state = data - return (property, property_name(property, int(from_state)), - property_name(property, int(to_state))) + return [property, property_name(property, int(from_state)), + property_name(property, int(to_state))] + def format_freshdesk_note_message(ticket, event_info): - # There are public (visible to customers) and private note types. + # type: (TicketDict, List[str]) -> str + """There are public (visible to customers) and private note types.""" note_type = event_info[1] content = "%s <%s> added a %s note to [ticket #%s](%s)." % ( ticket.requester_name, ticket.requester_email, note_type, @@ -67,10 +81,13 @@ def format_freshdesk_note_message(ticket, event_info): return content + def format_freshdesk_property_change_message(ticket, event_info): - # Freshdesk will only tell us the first event to match our webhook - # configuration, so if we change multiple properties, we only get the before - # and after data for the first one. + # type: (TicketDict, List[str]) -> str + """Freshdesk will only tell us the first event to match our webhook + configuration, so if we change multiple properties, we only get the before + and after data for the first one. + """ content = "%s <%s> updated [ticket #%s](%s):\n\n" % ( ticket.requester_name, ticket.requester_email, ticket.id, ticket.url) # Why not `"%s %s %s" % event_info`? Because the linter doesn't like it. @@ -79,8 +96,10 @@ def format_freshdesk_property_change_message(ticket, event_info): return content + def format_freshdesk_ticket_creation_message(ticket): - # They send us the description as HTML. + # type: (TicketDict) -> str + """They send us the description as HTML.""" cleaned_description = convert_html_to_markdown(ticket.description) content = "%s <%s> created [ticket #%s](%s):\n\n" % ( ticket.requester_name, ticket.requester_email, ticket.id, ticket.url) @@ -93,10 +112,12 @@ def format_freshdesk_ticket_creation_message(ticket): return content + @authenticated_rest_api_view @has_request_variables def api_freshdesk_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='freshdesk')): + # type: (HttpRequest, UserProfile, Dict[str, Any], text_type) -> HttpResponse ticket_data = payload["freshdesk_webhook"] required_keys = [