Пример #1
0
    def parse(self, method, payload):
        json = JSONParser.parse(self, method, payload)
        if len(json) == 1 and json.has_key('error_response'):
            raise TopError(payload)

        title_key = method.method_name.replace('taobao.', '').replace(
            '.', '_') + '_response'
        if not json.has_key(title_key):
            raise TopError('wrong response data')
        return TopObjectParser.json_to_object(json[title_key],
                                              method.field_mapping)
Пример #2
0
 def prev(self):
     if self.current_page is None:
         raise TopError('Can not go back more, at first page')
     if self.page_index == 0:
         # At the beginning of the current page, move to next...
         self.current_page = self.page_iterator.prev()
         self.page_index = len(self.current_page)
         if self.page_index == 0:
             raise TopError('No more items')
     self.page_index -= 1
     self.count -= 1
     return self.current_page[self.page_index]
Пример #3
0
 def prev(self):
     if self.prev_cursor == 0:
         raise TopError('Can not page back more, at first page')
     data, self.next_cursor, self.prev_cursor = self.method(
         cursor=self.prev_cursor, *self.args, **self.kargs)
     self.count -= 1
     return data
Пример #4
0
 def parse(self, method, payload):
     try:
         json = self.json_lib.loads(payload, strict=False)
     except Exception, e:
         # print "Failed to parse JSON payload:" + str(payload)
         from apps.common.utils.utils_log import log
         log.error('Failed to parse JSON payload: e=%s' % e)
         raise TopError(payload)
Пример #5
0
 def __init__(self, method, *args, **kargs):
     if hasattr(method, 'pagination_mode'):
         if method.pagination_mode == 'cursor':
             self.iterator = CursorIterator(method, args, kargs)
         else:
             self.iterator = PageIterator(method, args, kargs)
     else:
         raise TopError('This method does not perform pagination')
Пример #6
0
        def build_parameters(self, args, kargs):
            if args:
                raise TopError('argument name is necessary for API function!')
            self.parameters = {}
            for k, arg in kargs.items():
                # if arg is None: 最初代码是这样,不知道为什么,先注释掉吧
                #    continue
                if k == self.multi_para: # 如果是数据字段则不进行编码
                    self.parameters[k] = kargs[k]
                    continue

                if k in self.parameters:
                    raise TopError('Multiple values for parameter %s supplied!' % k)
                # self.parameters[k] = convert_2utf8_str(arg)
                is_str, self.parameters[k] = convert_arg_2utf8_str(arg)
                if not is_str and self.app_name: # 非字符串类型、并且是ztcjl的api
                    self.parameters[k + '__eval'] = convert_2utf8_str(1)
            if self.app_name: # added for ztcjl api_router
                self.parameters['app'] = self.app_name
            self.parameters['method'] = self.method_name
Пример #7
0
    def _pack_file(fieldname=None,
                   filename=None,
                   other_args={},
                   max_size=1024 * 10):
        # build the mulitpart-formdata body
        BOUNDARY = 'Tw3ePy'
        body = []
        for k, v in other_args.items():
            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="%s"' % (k))
            body.append('Content-Type: text/plain; charset=US-ASCII')
            body.append('Content-Transfer-Encoding: 8bit')
            body.append('')
            body.append(str(v))
        if filename:
            try:
                if max_size == -1:
                    pass
                elif os.path.getsize(filename) > (max_size * 1024):
                    raise TopError('File is too big, must be less than 10MB.')
            except os.error, e:
                raise TopError('Unable to access file, e=%s' % (e))

            file_type = mimetypes.guess_type(filename)
            file_type = file_type[0]
            if file_type is None:
                raise TopError('Could not determine file type')

            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="' + fieldname +
                        '"; filename="%s"' % filename)
            body.append('Content-Type: %s' % file_type)
            body.append('Content-Transfer-Encoding: binary')
            body.append('')
            fp = open(filename, 'rb')
            body.append(fp.read())
            fp.close()
            body.append('--' + BOUNDARY + '--')
            body.append('')
Пример #8
0
        def __init__(self, api, args, kargs):
            # If authentication is required and no credentials are provided, throw an error.
            if self.require_auth and (not api.auth or not api.auth.session_key):
                raise TopError('Authentication required!')

            self.api = api
            self.post_data = kargs.pop('post_data', None)
            self.retry_count = kargs.pop('retry_count', api.retry_count)
            self.retry_delay = kargs.pop('retry_delay', api.retry_delay)
            self.retry_errors = kargs.pop('retry_errors', api.retry_errors)
            self.is_quick_send = kargs.pop('is_quick_send', api.is_quick_send)
            self.headers = kargs.pop('headers', {})
            self.build_parameters(args, kargs)
            # Pick correct URL root to use

            if api.secure:
                self.scheme = 'https://'
            else:
                self.scheme = 'http://'
Пример #9
0
    def parse(self, method, payload):
        try:
            if method.payload_type is None: return
            model = getattr(self.model_factory, method.payload_type)
        except AttributeError:
            raise TopError('No model for this payload type: %s' %
                           method.payload_type)

        json = JSONParser.parse(self, method, payload)
        if isinstance(json, tuple):
            json, cursors = json
        else:
            cursors = None

        if method.payload_list:
            result = model.parse_list(method.api, json)
        else:
            result = model.parse(method.api, json)
        if cursors:
            return result, cursors
        else:
            return result
Пример #10
0
    def _pack_image(filename,
                    max_size,
                    source=None,
                    status=None,
                    lat=None,
                    long=None,
                    contentname="image"):
        """Pack image from file into multipart-formdata post body"""
        # image must be less than 700kb in size
        try:
            if os.path.getsize(filename) > (max_size * 1024):
                raise TopError('File is too big, must be less than 700kb.')
        # except os.error, e:
        except os.error:
            raise TopError('Unable to access file')

        # image must be gif, jpeg, or png
        file_type = mimetypes.guess_type(filename)
        if file_type is None:
            raise TopError('Could not determine file type')
        file_type = file_type[0]
        if file_type not in ['image/gif', 'image/jpeg', 'image/png']:
            raise TopError('Invalid file type for image: %s' % file_type)

        # build the mulitpart-formdata body
        fp = open(filename, 'rb')
        BOUNDARY = 'Tw3ePy'
        body = []
        if status is not None:
            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="status"')
            body.append('Content-Type: text/plain; charset=US-ASCII')
            body.append('Content-Transfer-Encoding: 8bit')
            body.append('')
            body.append(status)
        if source is not None:
            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="source"')
            body.append('Content-Type: text/plain; charset=US-ASCII')
            body.append('Content-Transfer-Encoding: 8bit')
            body.append('')
            body.append(source)
        if lat is not None:
            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="lat"')
            body.append('Content-Type: text/plain; charset=US-ASCII')
            body.append('Content-Transfer-Encoding: 8bit')
            body.append('')
            body.append(lat)
        if long is not None:
            body.append('--' + BOUNDARY)
            body.append('Content-Disposition: form-data; name="long"')
            body.append('Content-Type: text/plain; charset=US-ASCII')
            body.append('Content-Transfer-Encoding: 8bit')
            body.append('')
            body.append(long)
        body.append('--' + BOUNDARY)
        body.append('Content-Disposition: form-data; name="' + contentname +
                    '"; filename="%s"' % filename)
        body.append('Content-Type: %s' % file_type)
        body.append('Content-Transfer-Encoding: binary')
        body.append('')
        body.append(fp.read())
        body.append('--' + BOUNDARY + '--')
        body.append('')
        fp.close()
        body.append('--' + BOUNDARY + '--')
        body.append('')
        body = '\r\n'.join(body)
        # build headers
        headers = {
            'Content-Type': 'multipart/form-data; boundary=Tw3ePy',
            'Content-Length': len(body)
        }
        return headers, body
Пример #11
0
    class APIMethod(object):
        app_name = config.get('app_name', None)
        method_name = config.get('method_name', None)
        payload_type = config.get('payload_type', None)
        payload_list = config.get('payload_list', False)
        field_mapping = config.get('field_mapping', None)
        method = config.get('method', 'GET')
        require_auth = config.get('require_auth', False)
        multi_para = config.get('multi_para', None) # by:zhongjinfeng此字段是用来提交二进制数据的,比如上传图片的接口

        def __init__(self, api, args, kargs):
            # If authentication is required and no credentials are provided, throw an error.
            if self.require_auth and (not api.auth or not api.auth.session_key):
                raise TopError('Authentication required!')

            self.api = api
            self.post_data = kargs.pop('post_data', None)
            self.retry_count = kargs.pop('retry_count', api.retry_count)
            self.retry_delay = kargs.pop('retry_delay', api.retry_delay)
            self.retry_errors = kargs.pop('retry_errors', api.retry_errors)
            self.is_quick_send = kargs.pop('is_quick_send', api.is_quick_send)
            self.headers = kargs.pop('headers', {})
            self.build_parameters(args, kargs)
            # Pick correct URL root to use

            if api.secure:
                self.scheme = 'https://'
            else:
                self.scheme = 'http://'

            # Manually set Host header to fix an issue in python 2.5
            # or older where Host is set including the 443 port.
            # This causes Twitter to issue 301 redirect.
            # See Issue http://github.com/joshthecoder/tweepy/issues/#issue/12
            # 由于后面会使用到headers,因此这里并不需要,反而会造成connection与headers不一致(API流控)
            # 上面的英文说是修复Twitter的一个重定向bug,这里注释掉下面这句是可以的。
            # self.headers['Host'] = self.api.host

        def build_parameters(self, args, kargs):
            if args:
                raise TopError('argument name is necessary for API function!')
            self.parameters = {}
            for k, arg in kargs.items():
                # if arg is None: 最初代码是这样,不知道为什么,先注释掉吧
                #    continue
                if k == self.multi_para: # 如果是数据字段则不进行编码
                    self.parameters[k] = kargs[k]
                    continue

                if k in self.parameters:
                    raise TopError('Multiple values for parameter %s supplied!' % k)
                # self.parameters[k] = convert_2utf8_str(arg)
                is_str, self.parameters[k] = convert_arg_2utf8_str(arg)
                if not is_str and self.app_name: # 非字符串类型、并且是ztcjl的api
                    self.parameters[k + '__eval'] = convert_2utf8_str(1)
            if self.app_name: # added for ztcjl api_router
                self.parameters['app'] = self.app_name
            self.parameters['method'] = self.method_name

        def execute(self):
            # Build the request URL
            url = self.api.api_root
            parameters = {}
            parameters.update(self.parameters)
            if self.api.auth:
                if self.multi_para: # by:zhongjingfeng 此处如果是数据字段,则去除不参与签名
                    self.multi_para_data = parameters.pop(self.multi_para)
                self.api.auth.apply_auth(parameters = parameters)
            if len(parameters):
                if self.method == 'GET':
                    url = '%s?%s' % (url, urllib.urlencode(parameters))
                else:
                    self.headers.setdefault("User-Agent", "python")
                    if self.post_data is None:
                        self.headers.setdefault("Accept", "text/html")
                        self.headers.setdefault("Content-Type", "application/x-www-form-urlencoded")
                        self.post_data = urllib.urlencode(parameters)

                    if self.multi_para:
                        form = MultiPartForm()
                        for key, value in parameters.items():
                            form.add_field(key, value)
                        fileitem = self.multi_para_data
                        if(fileitem and isinstance(fileitem, FileItem)):
                            form.add_file(self.multi_para, fileitem.filename, fileitem.content)
                        self.post_data = str(form)
                        self.headers["Content-Type"] = form.get_content_type()

            # Query the cache if one is available and this request uses a GET method.
            if self.api.cache and self.method == 'GET':
                cache_result = self.api.cache.get(url)
                # if cache result found and not expired, return it
                if cache_result:
                    # must restore api reference
                    if isinstance(cache_result, list):
                        for result in cache_result:
                            result._api = self.api
                    else:
                        cache_result._api = self.api
                    return cache_result

            # Continue attempting request until successful or maximum number of retries is reached.
            resp = None
            sTime = time.time()
            retries_performed = 0
#             API_LOG = Config.get_value('common.API_LOG_OUTPUT', default = 0)
            while retries_performed < self.retry_count + 1:
                # Open connection
                api_host = self.api.host
                if self.api.timeout:
                    if self.api.secure:
                        conn = httplib.HTTPSConnection(api_host, timeout = self.api.timeout)
                    else:
                        conn = httplib.HTTPConnection(api_host, timeout = self.api.timeout)
                else:
                    if self.api.secure:
                        conn = httplib.HTTPSConnection(api_host)
                    else:
                        conn = httplib.HTTPConnection(api_host)

#                 if API_LOG in [1, 3]:
#                 log.info('url=%s, headers=%s, retries_performed=%s, retry_delay=%s' % (url, self.headers, retries_performed, self.retry_delay))

                # Execute request
                try:
                    conn.request(self.method, url, headers = self.headers, body = self.post_data)
                    if self.is_quick_send:
                        return {'result': True}
                    resp = conn.getresponse()
                except Exception, e:
                    log.error('Failed to send request, host=%s, url=%s, headers=%s, retries_performed=%s, retry_delay=%s, e=%s' % (api_host, url, self.headers, retries_performed, self.retry_delay, e))
                    time.sleep(self.retry_delay)
                    retries_performed += 1
                    continue

                # Exit request loop if non-retry error code
                if self.retry_errors:
                    # if resp.status not in self.retry_errors: break
                    pass
                else:
                    if resp.status == 200:
                        break

                # Sleep before retrying request again
                time.sleep(self.retry_delay)
                retries_performed += 1

            # If an error was returned, throw an exception
            try:
                body = resp.read()
                conn.close()
            except Exception, e:
                conn.close()
                raise TopError('%s' % e)
Пример #12
0
 def prev(self):
     if (self.current_page == 1):
         raise TopError('Can not page back more, at first page')
     self.current_page -= 1
     return self.method(page=self.current_page, *self.args, **self.kargs)