2020-01-21 06:35:58 +00:00
|
|
|
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
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
logger = logging.getLogger("judge.texoid")
|
2020-01-21 06:35:58 +00:00
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
TEXOID_ENABLED = hasattr(settings, "TEXOID_URL")
|
2020-01-21 06:35:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TexoidRenderer(object):
|
|
|
|
def __init__(self):
|
2022-05-14 17:57:27 +00:00
|
|
|
self.cache = HashFileCache(
|
|
|
|
settings.TEXOID_CACHE_ROOT, settings.TEXOID_CACHE_URL, settings.TEXOID_GZIP
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
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:
|
2022-05-14 17:57:27 +00:00
|
|
|
response = requests.post(
|
|
|
|
settings.TEXOID_URL,
|
|
|
|
data=utf8bytes(document),
|
|
|
|
headers={
|
|
|
|
"Content-Type": "application/x-tex",
|
|
|
|
},
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
response.raise_for_status()
|
|
|
|
except requests.HTTPError as e:
|
|
|
|
if e.response.status == 400:
|
2022-05-14 17:57:27 +00:00
|
|
|
logger.error(
|
|
|
|
"Texoid failed to render: %s\n%s", document, e.response.text
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
else:
|
2022-05-14 17:57:27 +00:00
|
|
|
logger.exception("Failed to connect to texoid for: %s", document)
|
2020-01-21 06:35:58 +00:00
|
|
|
return
|
|
|
|
except Exception:
|
2022-05-14 17:57:27 +00:00
|
|
|
logger.exception("Failed to connect to texoid for: %s", document)
|
2020-01-21 06:35:58 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
|
|
|
data = response.json()
|
|
|
|
except ValueError:
|
2022-05-14 17:57:27 +00:00
|
|
|
logger.exception(
|
|
|
|
"Invalid texoid response for: %s\n%s", document, response.text
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
return
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
if not data["success"]:
|
|
|
|
logger.error("Texoid failure for: %s\n%s", document, data)
|
|
|
|
return {"error": data["error"]}
|
2020-01-21 06:35:58 +00:00
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
meta = data["meta"]
|
|
|
|
self.cache.cache_data(
|
|
|
|
hash, "meta", utf8bytes(json.dumps(meta)), url=False, gzip=False
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
|
|
|
|
result = {
|
2022-05-14 17:57:27 +00:00
|
|
|
"png": self.cache.cache_data(hash, "png", b64decode(data["png"])),
|
|
|
|
"svg": self.cache.cache_data(hash, "svg", data["svg"].encode("utf-8")),
|
|
|
|
"meta": meta,
|
2020-01-21 06:35:58 +00:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
|
|
|
|
def query_cache(self, hash):
|
|
|
|
result = {
|
2022-05-14 17:57:27 +00:00
|
|
|
"svg": self.cache.get_url(hash, "svg"),
|
|
|
|
"png": self.cache.get_url(hash, "png"),
|
2020-01-21 06:35:58 +00:00
|
|
|
}
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
key = "texoid:meta:" + hash
|
2020-01-21 06:35:58 +00:00
|
|
|
cached_meta = self.meta_cache.get(key)
|
|
|
|
if cached_meta is None:
|
2022-05-14 17:57:27 +00:00
|
|
|
cached_meta = json.loads(self.cache.read_data(hash, "meta").decode("utf-8"))
|
2020-01-21 06:35:58 +00:00
|
|
|
self.meta_cache.set(key, cached_meta, self.meta_cache_ttl)
|
2022-05-14 17:57:27 +00:00
|
|
|
result["meta"] = cached_meta
|
2020-01-21 06:35:58 +00:00
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
def get_result(self, formula):
|
|
|
|
hash = hashlib.sha1(utf8bytes(formula)).hexdigest()
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
if self.cache.has_file(hash, "svg"):
|
2020-01-21 06:35:58 +00:00
|
|
|
return self.query_cache(hash)
|
|
|
|
else:
|
|
|
|
return self.query_texoid(formula, hash)
|