Skip to content

Commit

Permalink
#464: make breaking changes on onlinejudge.type
Browse files Browse the repository at this point in the history
  • Loading branch information
kmyk committed Aug 18, 2019
1 parent e5d78d3 commit 5927776
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 17 deletions.
15 changes: 14 additions & 1 deletion onlinejudge/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from typing import List, Optional, Type

import onlinejudge._implementation.logging as log
from onlinejudge.type import Problem, Service, Submission
from onlinejudge.type import Contest, Problem, Service, Submission

submissions = [] # type: List[Type['Submission']]

Expand Down Expand Up @@ -61,6 +61,19 @@ def problem_from_url(url: str) -> Optional[Problem]:
return None


contests = [] # type: List[Type['Contest']]


def contest_from_url(url: str) -> Optional[Contest]:
for cls in contests:
contest = cls.from_url(url)
if contest is not None:
log.status('contest recognized: %s: %s', str(contest), url)
return contest
log.failure('unknown contest: %s', url)
return None


services = [] # type: List[Type['Service']]


Expand Down
66 changes: 50 additions & 16 deletions onlinejudge/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ class LoginError(RuntimeError):


class Service(ABC):
def login(self, get_credentials: CredentialsProvider, session: Optional[requests.Session] = None) -> None:
def login(self, *, get_credentials: CredentialsProvider, session: Optional[requests.Session] = None) -> None:
"""
:param get_credentials: returns a tuple of (username, password)
:raises LoginError:
"""
raise NotImplementedError

def is_logged_in(self, session: Optional[requests.Session] = None) -> bool:
def is_logged_in(self, *, session: Optional[requests.Session] = None) -> bool:
raise NotImplementedError

@abstractmethod
Expand Down Expand Up @@ -50,13 +50,16 @@ def __eq__(self, other) -> bool:
def from_url(self, s: str) -> Optional['Service']:
pass

def iterate_contests(self, *, session: Optional[requests.Session] = None) -> Iterator['Contest']:
raise NotImplementedError


TestCase = NamedTuple('TestCase', [
('name', str),
('input_name', str),
('input_data', bytes),
('output_name', Optional[str]),
('output_data', Optional[bytes]),
('output_name', str),
('output_data', bytes),
])

LanguageId = NewType('LanguageId', str)
Expand All @@ -78,25 +81,54 @@ class NotLoggedInError(RuntimeError):
pass


class SampleParsingError(RuntimeError):
pass


class SubmissionError(RuntimeError):
pass


class Contest(ABC):
"""
:note: :py:class:`Contest` represents just a URL of a contest, without the data of the contest.
"""
def download_name(self, *, session: Optional[requests.Session] = None) -> str:
return self.download_content(session=session).name

def list_problems(self, *, session: Optional[requests.Session] = None) -> List['Problem']:
return self.download_content(session=session).problems

@abstractmethod
def download_content(self, *, session: Optional[requests.Session] = None) -> NamedTuple:
pass

def iterate_submissions(self, *, session: Optional[requests.Session] = None) -> Iterator['Submission']:
raise NotImplementedError


class Problem(ABC):
"""
:note: :py:class:`Problem` represents just a URL of a problem, without the data of the problem.
:py:class:`Problem` はちょうど問題の URL のみを表現します。キャッシュや内部状態は持ちません。
"""
@abstractmethod
def download_sample_cases(self, session: Optional[requests.Session] = None) -> List[TestCase]:
raise NotImplementedError
def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[TestCase]:
"""
:raises SampleParsingError:
"""
content = self.download_content(session=session)
if content.sample_cases is None:
raise SampleParsingError
return content.sample_cases

def download_system_cases(self, session: Optional[requests.Session] = None) -> List[TestCase]:
def download_system_cases(self, *, session: Optional[requests.Session] = None) -> List[TestCase]:
"""
:raises NotLoggedInError:
"""
raise NotImplementedError

def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> 'Submission':
def submit_code(self, code: bytes, language_id: LanguageId, *, filename: Optional[str] = None, session: Optional[requests.Session] = None) -> 'Submission':
"""
:param code:
:arg language_id: :py:class:`LanguageId`
Expand All @@ -105,7 +137,7 @@ def submit_code(self, code: bytes, language_id: LanguageId, filename: Optional[s
"""
raise NotImplementedError

def get_available_languages(self, session: Optional[requests.Session] = None) -> List[Language]:
def get_available_languages(self, *, session: Optional[requests.Session] = None) -> List[Language]:
raise NotImplementedError

@abstractmethod
Expand All @@ -116,21 +148,21 @@ def get_url(self) -> str:
def get_service(self) -> Service:
raise NotImplementedError

def get_name(self) -> str:
def download_name(self, *, session: Optional[requests.Session] = None) -> str:
"""
example:
- `器物損壊!高橋君`
- `AtCoDeerくんと変なじゃんけん / AtCoDeer and Rock-Paper`
- `Xor Sum`
"""
raise NotImplementedError
return self.download_content(session=session).name

def get_input_format(self, session: Optional[requests.Session] = None) -> Optional[str]:
@abstractmethod
def download_content(self, *, session: Optional[requests.Session] = None) -> NamedTuple:
"""
:return: the HTML in the `<pre>` tag as :py:class:`str`
:note: The returned values vary depending on the implementation.
"""

raise NotImplementedError

def __repr__(self) -> str:
Expand All @@ -146,8 +178,10 @@ def from_url(self, s: str) -> Optional['Problem']:


class Submission(ABC):
@abstractmethod
def download_code(self, session: Optional[requests.Session] = None) -> bytes:
def download_code(self, *, session: Optional[requests.Session] = None) -> bytes:
return self.download_content(session=session).source_code

def download_content(self, *, session: Optional[requests.Session] = None) -> NamedTuple:
raise NotImplementedError

@abstractmethod
Expand Down

0 comments on commit 5927776

Please sign in to comment.