Repository: kmyk/online-judge-tools
Pull request #504 (2019-08-24 17:25:31)

#461
close #461 

#461 を `develop` へマージします。


Patch:
diff --git a/onlinejudge/_implementation/main.py b/onlinejudge/_implementation/main.py
index 853f6b6..8c9fdf7 100644
--- a/onlinejudge/_implementation/main.py
+++ b/onlinejudge/_implementation/main.py
@@ -322,6 +322,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/service/atcoder.py b/onlinejudge/service/atcoder.py
index 887f502..3c87a08 100644
--- a/onlinejudge/service/atcoder.py
+++ b/onlinejudge/service/atcoder.py
@@ -655,7 +655,7 @@ class AtCoderProblemDetailedData(AtCoderProblemData):
     @classmethod
     def _parse_sample_cases(cls, soup: bs4.BeautifulSoup) -> List[onlinejudge.type.TestCase]:
         """
-        :raises SampleParsingError:
+        :raises SampleParseError:
         """
         samples = onlinejudge._implementation.testcase_zipper.SampleZipper()
         lang = None
@@ -725,7 +725,7 @@ class AtCoderProblemDetailedData(AtCoderProblemData):
         soup = bs4.BeautifulSoup(html, utils.html_parser)
         try:
             sample_cases = cls._parse_sample_cases(soup)  # type: Optional[List[TestCase]]
-        except SampleParsingError:
+        except SampleParseError:
             sample_cases = None
         input_format = cls._parse_input_format(soup)
         available_languages = cls._parse_available_languages(soup, problem=problem)
@@ -777,7 +777,7 @@ class AtCoderProblem(onlinejudge.type.Problem):
     def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[onlinejudge.type.TestCase]:
         """
         :raises requests.exceptions.HTTPError: if no such problem exists
-        :raises SampleParsingError: if parsing failed
+        :raises SampleParseError: if parsing failed
         """
         session = session or utils.get_default_session()
         resp = _request('GET', self.get_url(type='beta'), session=session)
diff --git a/onlinejudge/type.py b/onlinejudge/type.py
index 541ae30..48ff733 100644
--- a/onlinejudge/type.py
+++ b/onlinejudge/type.py
@@ -82,7 +82,7 @@ class NotLoggedInError(RuntimeError):
     pass
 
 
-class SampleParsingError(RuntimeError):
+class SampleParseError(RuntimeError):
     pass
 
 
@@ -209,7 +209,7 @@ class Problem(ABC):
     @abstractmethod
     def download_sample_cases(self, *, session: Optional[requests.Session] = None) -> List[TestCase]:
         """
-        :raises SampleParsingError:
+        :raises SampleParseError:
         """
         raise NotImplementedError
 


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')