Repository: kmyk/online-judge-tools
Pull request #552 (2019-10-15 15:01:56)

solve issue/192 (the case when <br> tag exists within <pre> tag)
In [no.750](https://yukicoder.me/problems/no/750) and [no.751](https://yukicoder.me/problems/no/751), the author have written sample case using `<br>` tag within `<pre>` tag, which is not a user concern but we might not have been expected.

<br>

For example,  [no.750](https://yukicoder.me/problems/no/750) サンプル1 入力1
`<pre>6<br />1 1<br />7 4<br />0 5<br />1 3<br />-8 9<br />5 1</pre>`
is given for online-judge-tools.

<br>

[Beautiful Soup documents](https://www.crummy.com/software/BeautifulSoup/bs4/doc/#string) says that
> If a tag contains more than one thing, then it’s not clear what `.string` should refer to, so `.string` is defined to be `None`:

<br>

So we should fix
`s = tag.string or ''  # tag.string for the tag "<pre></pre>" returns None`
(in `_parse_sample_tag` function, onlinejudge/service/yukicoder.py file).

<br>

In this pull request, I use `.strings` generator and iterate to make what the user expects.

<br>

But the unexpected behavior for the user will remain in some problems. (although I have never seen them in a real environment.)

Let me show a tricky problem.

**問題文**
文字列Sが1行で与えられる. Sは小文字のアルファベットと`<`と`>`を用いて構成される.
Sに含まれる`r`の個数を1行で出力しなさい.
**制約**
1 <= S <= 100
**サンプル**
入力1
<strong>yuki</strong>code<br>r
出力1
4

... because this problem's author thinks 入力1 as `<strong>yuki</strong>code<br>r`

In my opinion, user's expectation for `oj d` is to download what they see and we have not to handle with such tricky problems.



Patch:
diff --git a/onlinejudge/service/yukicoder.py b/onlinejudge/service/yukicoder.py
index c78053e..3ff576d 100644
--- a/onlinejudge/service/yukicoder.py
+++ b/onlinejudge/service/yukicoder.py
@@ -277,7 +277,16 @@ class YukicoderProblem(onlinejudge.type.Problem):
         if prv.name == 'h6' and tag.parent.name == 'div' and tag.parent['class'] == ['paragraph'] and pprv.name == 'h5':
             log.debug('h6: %s', str(prv))
             log.debug('name.encode(): %s', prv.string.encode())
-            s = tag.string or ''  # tag.string for the tag "<pre></pre>" returns None
+
+            # tag.string for the tag below returns None
+            # - "<pre></pre>"
+            # - "<pre>6<br />1 1<br />7 4<br />0 5<br />1 3<br />-8 9<br />5 1</pre>"
+            # for more details, see https://www.crummy.com/software/BeautifulSoup/bs4/doc/#string
+            if tag.string is not None:
+                s = tag.string
+            else:
+                s = bs4.NavigableString(''.join(string + '\n' for string in tag.strings))
+
             return utils.textfile(s.lstrip()), pprv.string + ' ' + prv.string
         return None
 


Test patch:
diff --git a/tests/service_yukicoder.py b/tests/service_yukicoder.py
index 8470d23..2dce380 100644
--- a/tests/service_yukicoder.py
+++ b/tests/service_yukicoder.py
@@ -46,7 +46,6 @@ class YukicoderProblemTest(unittest.TestCase):
             TestCase(name='sample-4', input_name='サンプル4 入力', input_data=b'1 1\n2\n', output_name='サンプル4 出力', output_data=b'-1\n'),
         ])
 
-    @unittest.expectedFailure
     def test_donwload_sample_cases_issue_192(self):
         # see https://github.com/kmyk/online-judge-tools/issues/192
         self.assertEqual(YukicoderProblem.from_url('https://yukicoder.me/problems/no/750').download_sample_cases(), [