Repository: kmyk/online-judge-tools
Pull request #626 (2019-12-02 13:31:41)

Raises error if no sample found.
When user use `download`, they expect any samples will be downloaded.
That means, if no samples are downloaded, it is unexpected behavior.
It is user friendly, `oj` shows error occurred explicitly.

```
$ oj d https://tdpc.contest.atcoder.jp/tasks/tdpc_contest
[x] GET: https://pypi.org/pypi/online-judge-tools/json
[x] 200 OK
[x] problem recognized: AtCoderProblem.from_url('https://atcoder.jp/contests/tdpc/tasks/tdpc_contest'): https://tdpc.contest.atcoder.jp/tasks/tdpc_contest
[x] load cookie from: /home/ryo/.local/share/online-judge-tools/cookie.jar
[x] GET: https://atcoder.jp/contests/tdpc/tasks/tdpc_contest
[x] 200 OK
[x] save cookie to: /home/ryo/.local/share/online-judge-tools/cookie.jar
[ERROR] Failed to parse sample.
```

kawacchu: There are two failed tests.

First, [test_call_download_hackerrank_hourrank_30_a_system](https://www.hackerrank.com/contests/hourrank-30/challenges/video-conference/problem) requires signup or login now.
This is not due to this PR.

Second, [test_call_download_kattis_hello](https://open.kattis.com/problems/hello) has no sample cases in it. Can you fix this?



Patch:
diff --git a/onlinejudge/_implementation/command/download.py b/onlinejudge/_implementation/command/download.py
index 9c169ae..515aeb5 100644
--- a/onlinejudge/_implementation/command/download.py
+++ b/onlinejudge/_implementation/command/download.py
@@ -44,6 +44,9 @@ def download(args: 'argparse.Namespace') -> None:
         else:
             samples = problem.download_sample_cases(session=sess)
 
+    if not samples:
+        raise onlinejudge.type.SampleParseError("Sample not found")
+
     # append the history for submit command
     if not args.dry_run and is_default_format:
         history = onlinejudge._implementation.download_history.DownloadHistory()


Test patch:
diff --git a/tests/command_download_invalid.py b/tests/command_download_invalid.py
index 039bdf7..ab64fcb 100644
--- a/tests/command_download_invalid.py
+++ b/tests/command_download_invalid.py
@@ -3,6 +3,8 @@ import unittest
 import requests.exceptions
 import tests.command_download
 
+from onlinejudge.type import SampleParseError
+
 
 class DownloadInvalid(unittest.TestCase):
     def snippet_call_download_raises(self, *args, **kwargs):
@@ -14,6 +16,10 @@ class DownloadInvalid(unittest.TestCase):
     def test_call_download_invalid(self):
         self.snippet_call_download_raises(requests.exceptions.InvalidURL, 'https://not_exist_contest.jp/tasks/001_a')
 
+    def test_call_download_no_sample_found(self):
+        self.snippet_call_download_raises(SampleParseError, 'https://atcoder.jp/contests/tenka1-2013-quala/tasks/tenka1_2013_qualA_a')
+        self.snippet_call_download_raises(SampleParseError, 'https://open.kattis.com/problems/hello')
+
     def test_call_download_twice(self):
         self.snippet_call_download_twice('https://atcoder.jp/contests/abc114/tasks/abc114_c', 'https://atcoder.jp/contests/abc003/tasks/abc003_4', [
             {
diff --git a/tests/command_download_kattis.py b/tests/command_download_kattis.py
index d5ba32b..53ab44e 100644
--- a/tests/command_download_kattis.py
+++ b/tests/command_download_kattis.py
@@ -29,7 +29,3 @@ class DownloadKattisTest(unittest.TestCase):
                 "output": "YES\nRRUULLD\nNO\nYES\nRD\n"
             },
         ], type='json')
-
-    def test_call_download_kattis_hello(self):
-        # there is no sample cases (and no samples.zip; it returns 404)
-        self.snippet_call_download('https://open.kattis.com/problems/hello', [], type='json')