import json import logging import os import sys from datetime import datetime, timedelta import tornado import tornado.gen import tornado.web from tornado.escape import utf8 from tornado.locks import Semaphore from apertium_apy.utils import to_fallback_code # Typing imports that flake8 doesn't understand: from typing import Union, Dict, Optional, List, Any, Tuple # noqa: F401 from apertium_apy.utils.translation import FlushingPipeline, SimplePipeline # noqa: F401 def dump_json(data): # This acts very similarly to Tornado's escape.json_encode but doesn't # result in ugly \u codes. Tornado does not support this natively. return json.dumps(data, ensure_ascii=False).replace(' self.stats.vmsize: logging.warning('VmSize of %s from %d to %d', os.getpid(), self.stats.vmsize, vmsize) self.stats.vmsize = vmsize except Exception as e: # Don't fail just because we couldn't log: logging.info('Exception in log_vmsize: %s', e) def send_response(self, data): self.log_vmsize() if isinstance(data, dict) or isinstance(data, list): data = dump_json(data) self.set_header('Content-Type', 'application/json; charset=UTF-8') if self.callback: self.set_header('Content-Type', 'application/javascript; charset=UTF-8') self._write_buffer.append(utf8('%s(%s)' % (self.callback, data))) else: self._write_buffer.append(utf8(data)) self.finish() def write_error(self, status_code, **kwargs): http_explanations = { 400: 'Request not properly formatted or contains languages that Apertium APy does not support', 404: 'Resource requested does not exist. URL may have been mistyped', 408: 'Server did not receive a complete request within the time it was prepared to wait. Try again', 500: 'Unexpected condition on server. Request could not be fulfilled.', } explanation = kwargs.get('explanation', http_explanations.get(status_code, '')) if 'exc_info' in kwargs and len(kwargs['exc_info']) > 1: exception = kwargs['exc_info'][1] if hasattr(exception, 'log_message') and exception.log_message: explanation = exception.log_message % exception.args elif hasattr(exception, 'reason'): explanation = exception.reason or tornado.httputil.responses.get(status_code, 'Unknown') else: explanation = tornado.httputil.responses.get(status_code, 'Unknown') result = { 'status': 'error', 'code': status_code, 'message': tornado.httputil.responses.get(status_code, 'Unknown'), 'explanation': explanation, } data = dump_json(result) self.set_header('Content-Type', 'application/json; charset=UTF-8') if self.callback: self.set_header('Content-Type', 'application/javascript; charset=UTF-8') self._write_buffer.append(utf8('%s(%s)' % (self.callback, data))) else: self._write_buffer.append(utf8(data)) self.finish() def set_default_headers(self): self.set_header('Access-Control-Allow-Origin', '*') self.set_header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS') self.set_header('Access-Control-Allow-Headers', 'accept, cache-control, origin, x-requested-with, x-file-name, content-type') def find_fallback_mode(self, in_mode, installed_modes): if in_mode not in installed_modes and '_' in in_mode: if in_mode in self.fallback_codes: in_mode = self.fallback_codes[in_mode] else: fallback_mode = to_fallback_code(in_mode, installed_modes) if fallback_mode is not None: self.fallback_codes[in_mode] = fallback_mode in_mode = fallback_mode return in_mode @tornado.gen.coroutine def post(self): yield self.get() def options(self): self.set_status(204) self.finish()