Source code for onlinejudge.service.kattis

# Python Version: 3.x
"""
the module for Kattis (https://open.kattis.com/)
"""

import re
import urllib.parse
from typing import *

import requests

import onlinejudge._implementation.logging as log
import onlinejudge._implementation.testcase_zipper
import onlinejudge._implementation.utils as utils
import onlinejudge.dispatch
import onlinejudge.type


[docs]class KattisService(onlinejudge.type.Service):
[docs] def get_url(self) -> str: """ :note: sometimes this URL is not correct, i.e. something like https://hanoi18.kattis.com/ exists """ return 'https://open.kattis.com/'
[docs] def get_name(self) -> str: return 'Kattis'
[docs] @classmethod def from_url(cls, url: str) -> Optional['KattisService']: # example: https://open.kattis.com/ # example: https://hanoi18.kattis.com/ result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc.endswith('.kattis.com'): # NOTE: ignore the subdomain return cls() return None
[docs]class KattisProblem(onlinejudge.type.Problem): def __init__(self, *, problem_id: str, contest_id: Optional[str] = None, domain: str = 'open.kattis.com'): self.domain = domain self.contest_id = contest_id self.problem_id = problem_id
[docs] def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[onlinejudge.type.TestCase]: session = session or utils.get_default_session() # get url = self.get_url(contests=False) + '/file/statement/samples.zip' resp = utils.request('GET', url, session=session, raise_for_status=False) if resp.status_code == 404: log.warning('samples.zip not found') log.info('this 404 happens in both cases: 1. no sample cases as intended; 2. just an error') return [] resp.raise_for_status() # parse return onlinejudge._implementation.testcase_zipper.extract_from_zip(resp.content, '%s.%e', out='ans')
[docs] def get_url(self, *, contests: bool = True) -> str: if contests and self.contest_id is not None: # the URL without "/contests/{}" also works return 'https://{}/contests/{}/problems/{}'.format(self.domain, self.contest_id, self.problem_id) else: return 'https://{}/problems/{}'.format(self.domain, self.problem_id)
[docs] def get_service(self) -> KattisService: # NOTE: ignore the subdomain return KattisService()
[docs] @classmethod def from_url(cls, url: str) -> Optional['KattisProblem']: # example: https://open.kattis.com/problems/hello # example: https://open.kattis.com/contests/asiasg15prelwarmup/problems/8queens result = urllib.parse.urlparse(url) if result.scheme in ('', 'http', 'https') \ and result.netloc.endswith('.kattis.com'): m = re.match(r'(?:/contests/([0-9A-Z_a-z-]+))?/problems/([0-9A-Z_a-z-]+)/?', result.path) if m: contest_id = m.group(1) or None problem_id = m.group(2) return cls(problem_id=problem_id, contest_id=contest_id, domain=result.netloc) return None
onlinejudge.dispatch.services += [KattisService] onlinejudge.dispatch.problems += [KattisProblem]