1# Tweepy 2# Copyright 2009-2020 Joshua Roesslein 3# See LICENSE for details. 4 5import json as json_lib 6 7from tweepy.error import TweepError 8from tweepy.models import ModelFactory 9 10 11class Parser(object): 12 13 def parse(self, method, payload, *args, **kwargs): 14 """ 15 Parse the response payload and return the result. 16 Returns a tuple that contains the result data and the cursors 17 (or None if not present). 18 """ 19 raise NotImplementedError 20 21 def parse_error(self, payload): 22 """ 23 Parse the error message and api error code from payload. 24 Return them as an (error_msg, error_code) tuple. If unable to parse the 25 message, throw an exception and default error message will be used. 26 """ 27 raise NotImplementedError 28 29 30class RawParser(Parser): 31 32 def __init__(self): 33 pass 34 35 def parse(self, method, payload, *args, **kwargs): 36 return payload 37 38 def parse_error(self, payload): 39 return payload 40 41 42class JSONParser(Parser): 43 44 payload_format = 'json' 45 46 def parse(self, method, payload, return_cursors=False): 47 try: 48 json = json_lib.loads(payload) 49 except Exception as e: 50 raise TweepError('Failed to parse JSON payload: %s' % e) 51 52 if return_cursors and isinstance(json, dict): 53 if 'next' in json: 54 return json, json['next'] 55 elif 'next_cursor' in json: 56 if 'previous_cursor' in json: 57 cursors = json['previous_cursor'], json['next_cursor'] 58 return json, cursors 59 else: 60 return json, json['next_cursor'] 61 return json 62 63 def parse_error(self, payload): 64 error_object = json_lib.loads(payload) 65 66 if 'error' in error_object: 67 reason = error_object['error'] 68 api_code = error_object.get('code') 69 else: 70 reason = error_object['errors'] 71 api_code = [error.get('code') for error in 72 reason if error.get('code')] 73 api_code = api_code[0] if len(api_code) == 1 else api_code 74 75 return reason, api_code 76 77 78class ModelParser(JSONParser): 79 80 def __init__(self, model_factory=None): 81 JSONParser.__init__(self) 82 self.model_factory = model_factory or ModelFactory 83 84 def parse(self, method, payload, return_cursors=False): 85 try: 86 if method.payload_type is None: 87 return 88 model = getattr(self.model_factory, method.payload_type) 89 except AttributeError: 90 raise TweepError('No model for this payload type: ' 91 '%s' % method.payload_type) 92 93 json = JSONParser.parse(self, method, payload, return_cursors=return_cursors) 94 if isinstance(json, tuple): 95 json, cursors = json 96 else: 97 cursors = None 98 99 if method.payload_list: 100 result = model.parse_list(method.api, json) 101 else: 102 result = model.parse(method.api, json) 103 104 if cursors: 105 return result, cursors 106 else: 107 return result 108