Repository: kmyk/online-judge-tools (python)

Issue:
a example of a problem whose sample cases have no outputs
取得に失敗してる。

https://chokudai001.contest.atcoder.jp/tasks/chokudai_001_a

AtCoder だとテストは入力と出力が常に揃っていてほしいし失敗でよさそう。下手にやると他のでゴミをサンプルだとして拾ってしまう。
しかしインターフェースはこれを返せるようになっているのに返さないのは混乱を生みそう。ちょっと困る。たぶんこのまま失敗させておくのが正解。

いずれにせよテストに足して挙動を明示しておいた方がよい。

Pull request description:
Raise error if sample parse failed.
Resolve #413 

413で例外を投げるようにしました。
エラーメッセージがわかるようなわからないような感じだったので、サンプルのパースに失敗したことをメッセージ煮だすようにしました。
また、従来、中途半端にsample.in/outが残っていましたが、怪しいのでなにも残さないようにしてみました。

Patch:
diff --git a/onlinejudge/_implementation/main.py b/onlinejudge/_implementation/main.py
index fa15b0d..d86e555 100644
--- a/onlinejudge/_implementation/main.py
+++ b/onlinejudge/_implementation/main.py
@@ -297,6 +297,9 @@ def main(args: Optional[List[str]] = None) -> None:
         log.error(str(e))
         log.debug(traceback.format_exc())
         sys.exit(1)
+    except onlinejudge.type.SampleParseError:
+        log.error('Failed to parse sample.')
+        sys.exit(1)
 
 
 if __name__ == '__main__':
diff --git a/onlinejudge/type.py b/onlinejudge/type.py
index bbaacf0..b4025e3 100644
--- a/onlinejudge/type.py
+++ b/onlinejudge/type.py
@@ -82,6 +82,10 @@ class SubmissionError(RuntimeError):
     pass
 
 
+class SampleParseError(RuntimeError):
+    pass
+
+
 class Problem(ABC):
     """
     :note: :py:class:`Problem` represents just a URL of a problem, without the data of the problem.


Test patch:
diff --git a/onlinejudge/_implementation/testcase_zipper.py b/onlinejudge/_implementation/testcase_zipper.py
index f4be98d..69845df 100644
--- a/onlinejudge/_implementation/testcase_zipper.py
+++ b/onlinejudge/_implementation/testcase_zipper.py
@@ -33,6 +33,7 @@ class SampleZipper(object):
     def get(self) -> List[TestCase]:
         if self._dangling is not None:
             log.error('dangling sample string: %s', self._dangling[1])
+            raise SampleParseError
         return self._testcases
 
 
diff --git a/tests/command_download_atcoder.py b/tests/command_download_atcoder.py
index 096c21a..5481158 100644
--- a/tests/command_download_atcoder.py
+++ b/tests/command_download_atcoder.py
@@ -3,6 +3,8 @@ import unittest
 import requests.exceptions
 import tests.command_download
 
+from onlinejudge.type import SampleParseError
+
 
 class DownloadAtCoderTest(unittest.TestCase):
     def snippet_call_download(self, *args, **kwargs):
@@ -131,3 +133,7 @@ class DownloadAtCoderTest(unittest.TestCase):
 
     def test_call_download_invalid_url(self):
         self.snippet_call_download_raises(requests.exceptions.HTTPError, 'http://abc001.contest.atcoder.jp/tasks/abc001_100')
+
+    def test_call_download_413(self):
+        # This task is not supported.
+        self.snippet_call_download_raises(SampleParseError, 'https://chokudai001.contest.atcoder.jp/tasks/chokudai_001_a')