86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
|
import hashlib
|
||
|
import json
|
||
|
import logging
|
||
|
from base64 import b64decode
|
||
|
|
||
|
import requests
|
||
|
from django.conf import settings
|
||
|
from django.core.cache import caches
|
||
|
|
||
|
from judge.utils.file_cache import HashFileCache
|
||
|
from judge.utils.unicode import utf8bytes
|
||
|
|
||
|
logger = logging.getLogger('judge.texoid')
|
||
|
|
||
|
TEXOID_ENABLED = hasattr(settings, 'TEXOID_URL')
|
||
|
|
||
|
|
||
|
class TexoidRenderer(object):
|
||
|
def __init__(self):
|
||
|
self.cache = HashFileCache(settings.TEXOID_CACHE_ROOT,
|
||
|
settings.TEXOID_CACHE_URL,
|
||
|
settings.TEXOID_GZIP)
|
||
|
self.meta_cache = caches[settings.TEXOID_META_CACHE]
|
||
|
self.meta_cache_ttl = settings.TEXOID_META_CACHE_TTL
|
||
|
|
||
|
def query_texoid(self, document, hash):
|
||
|
self.cache.create(hash)
|
||
|
|
||
|
try:
|
||
|
response = requests.post(settings.TEXOID_URL, data=utf8bytes(document), headers={
|
||
|
'Content-Type': 'application/x-tex',
|
||
|
})
|
||
|
response.raise_for_status()
|
||
|
except requests.HTTPError as e:
|
||
|
if e.response.status == 400:
|
||
|
logger.error('Texoid failed to render: %s\n%s', document, e.response.text)
|
||
|
else:
|
||
|
logger.exception('Failed to connect to texoid for: %s', document)
|
||
|
return
|
||
|
except Exception:
|
||
|
logger.exception('Failed to connect to texoid for: %s', document)
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
data = response.json()
|
||
|
except ValueError:
|
||
|
logger.exception('Invalid texoid response for: %s\n%s', document, response.text)
|
||
|
return
|
||
|
|
||
|
if not data['success']:
|
||
|
logger.error('Texoid failure for: %s\n%s', document, data)
|
||
|
return {'error': data['error']}
|
||
|
|
||
|
meta = data['meta']
|
||
|
self.cache.cache_data(hash, 'meta', utf8bytes(json.dumps(meta)), url=False, gzip=False)
|
||
|
|
||
|
result = {
|
||
|
'png': self.cache.cache_data(hash, 'png', b64decode(data['png'])),
|
||
|
'svg': self.cache.cache_data(hash, 'svg', data['svg'].encode('utf-8')),
|
||
|
'meta': meta,
|
||
|
}
|
||
|
return result
|
||
|
|
||
|
def query_cache(self, hash):
|
||
|
result = {
|
||
|
'svg': self.cache.get_url(hash, 'svg'),
|
||
|
'png': self.cache.get_url(hash, 'png'),
|
||
|
}
|
||
|
|
||
|
key = 'texoid:meta:' + hash
|
||
|
cached_meta = self.meta_cache.get(key)
|
||
|
if cached_meta is None:
|
||
|
cached_meta = json.loads(self.cache.read_data(hash, 'meta').decode('utf-8'))
|
||
|
self.meta_cache.set(key, cached_meta, self.meta_cache_ttl)
|
||
|
result['meta'] = cached_meta
|
||
|
|
||
|
return result
|
||
|
|
||
|
def get_result(self, formula):
|
||
|
hash = hashlib.sha1(utf8bytes(formula)).hexdigest()
|
||
|
|
||
|
if self.cache.has_file(hash, 'svg'):
|
||
|
return self.query_cache(hash)
|
||
|
else:
|
||
|
return self.query_texoid(formula, hash)
|