Skip to content

Commit

Permalink
Show Coverage Badge (#31)
Browse files Browse the repository at this point in the history
* #30 run codecov in CI

* #30 Update README.md

* #30 Add nose to Travis CI's dependency

* #30 make failed assertion readable

* #30 make a unit test more descriptive when failing

* #30 fix an existing bug that causes wrong casting during type prediction

* #30 set correct target package to test
  • Loading branch information
kyuridenamida committed Dec 25, 2018
1 parent 5d56d06 commit 5d4da07
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ do_format.py
debug.py
/backup
.idea
.coverage
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ python:
install:
- pip install bs4
- pip install flake8 autopep8
- pip install codecov nose

script:
- flake8 --ignore=E501, W605
- autopep8 -r . --diff | tee check_autopep8
- test ! -s check_autopep8
- ./atcoder-tool gen arc050 --without-login --no_parallel

- nosetests --with-coverage --cover-package=atcodertools
- codecov
notifications:
email: false
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.org/kyuridenamida/atcoder-tools.svg?branch=master)](https://travis-ci.org/kyuridenamida/atcoder-tools)
[![codecov](https://codecov.io/gh/kyuridenamida/atcoder-tools/branch/master/graph/badge.svg)](https://codecov.io/gh/kyuridenamida/atcoder-tools)

atcoder-tools
====
Expand Down
28 changes: 22 additions & 6 deletions atcodertools/fmtprediction/predict_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,28 @@ class InvalidLoopIndexError(Exception):
pass


UP_CAST_TABLE = {int: {}, str: {}, float: {}}

UP_CAST_TABLE[int][int] = int
UP_CAST_TABLE[int][str] = str
UP_CAST_TABLE[int][float] = float

UP_CAST_TABLE[str] = {}
UP_CAST_TABLE[str][int] = str
UP_CAST_TABLE[str][str] = str
UP_CAST_TABLE[str][float] = str

UP_CAST_TABLE[float] = {}
UP_CAST_TABLE[float][int] = float
UP_CAST_TABLE[float][str] = str
UP_CAST_TABLE[float][float] = float


def up_cast(old_type, new_type):
if old_type == new_type:
return old_type
if (old_type == int and new_type == float) or (old_type == float or new_type == int):
return float
raise UpCastingError
try:
return UP_CAST_TABLE[old_type][new_type]
except KeyError:
raise UpCastingError


def is_float(text):
Expand Down Expand Up @@ -155,7 +171,7 @@ def type_predictor(fmt: SimpleFormat, samples: List[Sample]) -> Dict[str, type]:
res_type_dict,
predictor.get_typing_result())
except (
TooLessFetchesError, TooManyFetchesError, KeyError, InvalidLoopSizeError, UpCastingError,
TooLessFetchesError, TooManyFetchesError, KeyError, InvalidLoopSizeError, UpCastingError,
InvalidLoopIndexError):
raise TypePredictionFailedError

Expand Down
24 changes: 12 additions & 12 deletions tests/resources/test_fmtprediction/answer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ abc083-B OK [(Singular: N),(Si
abc083-C OK [(Singular: X),(Singular: Y)] [('X', <class 'int'>), ('Y', <class 'int'>)]
abc083-D OK [(Singular: S)] [('S', <class 'int'>)]
abc084-A OK [(Singular: M)] [('M', <class 'int'>)]
abc084-B OK [(Singular: A),(Singular: B),(Singular: S)] [('A', <class 'int'>), ('B', <class 'int'>), ('S', <class 'float'>)]
abc084-B OK [(Singular: A),(Singular: B),(Singular: S)] [('A', <class 'int'>), ('B', <class 'int'>), ('S', <class 'str'>)]
abc084-C OK [(Singular: N),(Parallel: C,S,F | 1 to N-1)] [('N', <class 'int'>), ('C', <class 'int'>), ('S', <class 'int'>), ('F', <class 'int'>)]
abc084-D OK [(Singular: Q),(Parallel: l,r | 1 to Q)] [('Q', <class 'int'>), ('l', <class 'int'>), ('r', <class 'int'>)]
abc085-A OK [(Singular: S)] [('S', <class 'str'>)]
Expand Down Expand Up @@ -638,8 +638,8 @@ agc028-B OK [(Singular: N),(Pa
agc028-C OK [(Singular: N),(Parallel: A,B | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
agc028-D OK [(Singular: N),(Singular: K),(Parallel: A,B | 1 to K)] [('N', <class 'int'>), ('K', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
agc028-E OK [(Singular: N),(Parallel: P | 1 to N)] [('N', <class 'int'>), ('P', <class 'int'>)]
agc028-F No result
agc028-F2 No result
agc028-F OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'str'>)]
agc028-F2 OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'str'>)]
agc029-A OK [(Singular: S)] [('S', <class 'str'>)]
agc029-B OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>)]
agc029-C OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>)]
Expand Down Expand Up @@ -1470,13 +1470,13 @@ code-thanks-festival-2018-open-F OK [(Singular: N),(Si
code-thanks-festival-2018-open-G OK [(Singular: N),(Singular: K),(Parallel: a | 1 to N),(Parallel: b | 1 to N)] [('N', <class 'int'>), ('K', <class 'int'>), ('a', <class 'int'>), ('b', <class 'int'>)]
code-thanks-festival-2018-open-H OK [(Singular: N),(Parallel: a | 1 to N)] [('N', <class 'int'>), ('a', <class 'int'>)]
colopl2018-final-A OK [(Singular: N),(Singular: S)] [('N', <class 'int'>), ('S', <class 'str'>)]
colopl2018-final-B OK [(Singular: S)] [('S', <class 'float'>)]
colopl2018-final-B OK [(Singular: S)] [('S', <class 'str'>)]
colopl2018-final-C OK [(Singular: N),(Parallel: a | 1 to N)] [('N', <class 'int'>), ('a', <class 'int'>)]
colopl2018-final-D OK [(Singular: N),(Parallel: A,B | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
colopl2018-final-E OK [(Singular: H),(Singular: W),(Parallel: A | 1 to W)] [('H', <class 'int'>), ('W', <class 'int'>), ('A', <class 'int'>)]
colopl2018-final-F OK [(Singular: N),(Singular: L),(Singular: R)] [('N', <class 'int'>), ('L', <class 'int'>), ('R', <class 'int'>)]
colopl2018-final-open-A OK [(Singular: N),(Singular: S)] [('N', <class 'int'>), ('S', <class 'str'>)]
colopl2018-final-open-B OK [(Singular: S)] [('S', <class 'float'>)]
colopl2018-final-open-B OK [(Singular: S)] [('S', <class 'str'>)]
colopl2018-final-open-C OK [(Singular: N),(Parallel: a | 1 to N)] [('N', <class 'int'>), ('a', <class 'int'>)]
colopl2018-final-open-D OK [(Singular: N),(Parallel: A,B | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
colopl2018-final-open-E OK [(Singular: H),(Singular: W),(Parallel: A | 1 to W)] [('H', <class 'int'>), ('W', <class 'int'>), ('A', <class 'int'>)]
Expand Down Expand Up @@ -1523,11 +1523,11 @@ donuts-2015-A OK [(Singular: R),(Si
donuts-2015-B No result
donuts-2015-C OK [(Singular: N),(Parallel: H | 1 to N)] [('N', <class 'int'>), ('H', <class 'int'>)]
donuts-2015-D OK [(Singular: N),(Singular: K),(Parallel: C | 1 to N),(Singular: Q),(Parallel: D | 1 to Q)] [('N', <class 'int'>), ('K', <class 'int'>), ('C', <class 'int'>), ('Q', <class 'int'>), ('D', <class 'int'>)]
dwacon2017-honsen-A OK [(Singular: K),(Singular: S)] [('K', <class 'int'>), ('S', <class 'float'>)]
dwacon2017-honsen-A OK [(Singular: K),(Singular: S)] [('K', <class 'int'>), ('S', <class 'str'>)]
dwacon2017-honsen-B OK [(Singular: N),(Singular: Q),(Parallel: x | 1 to N),(Parallel: l,r | 1 to Q)] [('N', <class 'int'>), ('Q', <class 'int'>), ('x', <class 'int'>), ('l', <class 'int'>), ('r', <class 'int'>)]
dwacon2017-honsen-D No result
dwacon2017-prelims-A OK [(Singular: n),(Singular: a),(Singular: b)] [('n', <class 'int'>), ('a', <class 'int'>), ('b', <class 'int'>)]
dwacon2017-prelims-B OK [(Singular: T)] [('T', <class 'float'>)]
dwacon2017-prelims-B OK [(Singular: T)] [('T', <class 'str'>)]
dwacon2017-prelims-C OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>)]
dwacon2017-prelims-D OK [(Singular: N),(Singular: M),(Parallel: X,Y | 1 to N)] [('N', <class 'int'>), ('M', <class 'int'>), ('X', <class 'int'>), ('Y', <class 'int'>)]
dwacon2017-prelims-E OK [(Singular: N),(Parallel: A | 1 to N),(Singular: Q),(Parallel: K,X | 1 to Q)] [('N', <class 'int'>), ('A', <class 'int'>), ('Q', <class 'int'>), ('K', <class 'int'>), ('X', <class 'int'>)]
Expand All @@ -1548,11 +1548,11 @@ dwacon5th-prelims-B OK [(Singular: N),(Si
dwacon5th-prelims-C OK [(Singular: N),(Singular: S),(Singular: Q),(Parallel: k | 0 to Q-1)] [('N', <class 'int'>), ('S', <class 'str'>), ('Q', <class 'int'>), ('k', <class 'int'>)]
dwacon5th-prelims-D OK [(Singular: N),(Singular: D),(Parallel: x,y | 1 to N)] [('N', <class 'int'>), ('D', <class 'int'>), ('x', <class 'int'>), ('y', <class 'int'>)]
dwacon5th-prelims-E No result
dwango2015-finals-A OK [(Singular: N),(Singular: X),(Singular: S)] [('N', <class 'int'>), ('X', <class 'int'>), ('S', <class 'float'>)]
dwango2015-finals-A OK [(Singular: N),(Singular: X),(Singular: S)] [('N', <class 'int'>), ('X', <class 'int'>), ('S', <class 'str'>)]
dwango2015-finals-B OK [(Singular: N),(Parallel: S | 1 to N)] [('N', <class 'int'>), ('S', <class 'str'>)]
dwango2015-finals-C OK [(Singular: N),(Singular: M),(Parallel: A,B | 1 to M)] [('N', <class 'int'>), ('M', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
dwango2015-finals-D OK [(Singular: N),(Parallel: S | 1 to N),(Singular: Q),(Parallel: P,D | 1 to Q)] [('N', <class 'int'>), ('S', <class 'int'>), ('Q', <class 'int'>), ('P', <class 'int'>), ('D', <class 'int'>)]
dwango2015-honsen-A OK [(Singular: N),(Singular: X),(Singular: S)] [('N', <class 'int'>), ('X', <class 'int'>), ('S', <class 'float'>)]
dwango2015-honsen-A OK [(Singular: N),(Singular: X),(Singular: S)] [('N', <class 'int'>), ('X', <class 'int'>), ('S', <class 'str'>)]
dwango2015-honsen-B OK [(Singular: N),(Parallel: S | 1 to N)] [('N', <class 'int'>), ('S', <class 'str'>)]
dwango2015-honsen-C OK [(Singular: N),(Singular: M),(Parallel: A,B | 1 to M)] [('N', <class 'int'>), ('M', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
dwango2015-honsen-D OK [(Singular: N),(Parallel: S | 1 to N),(Singular: Q),(Parallel: P,D | 1 to Q)] [('N', <class 'int'>), ('S', <class 'int'>), ('Q', <class 'int'>), ('P', <class 'int'>), ('D', <class 'int'>)]
Expand Down Expand Up @@ -1665,7 +1665,7 @@ jag2017summer-day1-A OK [(Singular: N)] [(
jag2017summer-day1-B OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>)]
jag2017summer-day1-C OK [(Singular: N),(Singular: M),(Parallel: A | 1 to N),(Parallel: B | 1 to M)] [('N', <class 'int'>), ('M', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
jag2017summer-day1-D OK [(Singular: X),(Singular: Y),(Singular: Z)] [('X', <class 'int'>), ('Y', <class 'int'>), ('Z', <class 'int'>)]
jag2017summer-day1-E OK [(Singular: S)] [('S', <class 'float'>)]
jag2017summer-day1-E OK [(Singular: S)] [('S', <class 'str'>)]
jag2017summer-day1-F OK [(Singular: S),(Singular: Q),(Parallel: T | 1 to Q)] [('S', <class 'str'>), ('Q', <class 'int'>), ('T', <class 'str'>)]
jag2017summer-day1-G OK [(Singular: N),(TwoDimensional: A)] [('N', <class 'int'>), ('A', <class 'int'>)]
jag2017summer-day1-H OK [(Singular: X),(Singular: Y)] [('X', <class 'int'>), ('Y', <class 'int'>)]
Expand Down Expand Up @@ -2029,7 +2029,7 @@ tenka1-2018-beginner-D OK [(Singular: N)] [(
tkppc-A OK [(Singular: N),(Parallel: A,B | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>)]
tkppc-B OK [(Singular: N),(Parallel: A | 1 to N)] [('N', <class 'int'>), ('A', <class 'int'>)]
tkppc-C OK [(Singular: N),(Singular: M),(Singular: S),(Parallel: T,K | 1 to N)] [('N', <class 'int'>), ('M', <class 'int'>), ('S', <class 'int'>), ('T', <class 'int'>), ('K', <class 'int'>)]
tkppc-D No result
tkppc-D OK [(Singular: N),(Singular: R),(Singular: C),(Parallel: S | 1 to N*R)] [('N', <class 'int'>), ('R', <class 'int'>), ('C', <class 'int'>), ('S', <class 'str'>)]
tkppc-E OK [(Singular: N),(Parallel: A,B,C | 1 to N-1)] [('N', <class 'int'>), ('A', <class 'int'>), ('B', <class 'int'>), ('C', <class 'int'>)]
tkppc-F OK [(Singular: N),(Singular: M),(Parallel: P,Q,K | 1 to M)] [('N', <class 'int'>), ('M', <class 'int'>), ('P', <class 'int'>), ('Q', <class 'int'>), ('K', <class 'int'>)]
tkppc-G OK [(Singular: N),(Singular: S)] [('N', <class 'int'>), ('S', <class 'int'>)]
Expand Down Expand Up @@ -2098,7 +2098,7 @@ utpc2014-C OK [(Singular: n),(Pa
utpc2014-D OK [(Singular: m),(Parallel: rx,ry | 1 to m),(Singular: n),(Parallel: px,py,s,t | 1 to n)] [('m', <class 'int'>), ('rx', <class 'int'>), ('ry', <class 'int'>), ('n', <class 'int'>), ('px', <class 'int'>), ('py', <class 'int'>), ('s', <class 'int'>), ('t', <class 'int'>)]
utpc2014-E OK [(Singular: n),(Parallel: a,b | 1 to n)] [('n', <class 'int'>), ('a', <class 'int'>), ('b', <class 'int'>)]
utpc2014-F OK [(Singular: T),(Parallel: a | 1 to T)] [('T', <class 'int'>), ('a', <class 'int'>)]
utpc2014-G No result
utpc2014-G OK [(Singular: n),(Singular: X),(Singular: P),(Parallel: a | 1 to n)] [('n', <class 'int'>), ('X', <class 'int'>), ('P', <class 'int'>), ('a', <class 'str'>)]
utpc2014-H No result
utpc2014-I No result
utpc2014-J OK [(Singular: N),(Parallel: x,a | 1 to N),(Singular: Q),(Parallel: c,y,b | 1 to Q)] [('N', <class 'int'>), ('x', <class 'int'>), ('a', <class 'int'>), ('Q', <class 'int'>), ('c', <class 'int'>), ('y', <class 'int'>), ('b', <class 'int'>)]
Expand Down
22 changes: 21 additions & 1 deletion tests/test_fmtprediction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import tempfile
import unittest
import os
Expand All @@ -9,6 +10,9 @@
os.path.dirname(os.path.abspath(__file__)),
'./resources/test_fmtprediction/answer.txt')

fmt = "%(asctime)s %(levelname)s: %(message)s"
logging.basicConfig(level=logging.DEBUG, format=fmt)


class TestFormatPrediction(unittest.TestCase):

Expand All @@ -27,6 +31,7 @@ def test_overall(self):
output_text = ""
for case in case_names:
response = runner.run(case)

if response.status == "OK":
output_text += "{:40} {:20} {} {}\n".format(case, response.status, response.simple_format,
response.types)
Expand All @@ -35,7 +40,22 @@ def test_overall(self):

with open(ANSWER_FILE, 'r') as f:
answer = f.read()
self.assertEqual(answer, output_text)

for ans, out in zip(answer.split("\n"), output_text.split("\n")):
if ans != out:
# Case name is expected to be stored to the first column in the
# file.
case_name = ans.split()[0]
content = runner.load_problem_content(case_name)
logging.debug("=== {} ===".format(case_name))
logging.debug(
"Input Format:\n{}".format(content.input_format_text))
for idx, s in enumerate(content.samples):
logging.debug(
"Sample Input {num}:\n{inp}".format(inp=s.get_input(), num=idx + 1))
self.assertEqual(ans, out)

self.assertEqual(len(answer), len(output_text))


if __name__ == "__main__":
Expand Down
13 changes: 9 additions & 4 deletions tests/utils/fmtprediction_test_runner.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
from typing import Optional

from atcodertools.fmtprediction.predict_format import FormatPredictor, MultiplePredictionResultsError, NoPredictionResultError
from atcodertools.fmtprediction.predict_format import FormatPredictor, MultiplePredictionResultsError, \
NoPredictionResultError
from atcodertools.models.problem_content import ProblemContent
from atcodertools.models.sample import Sample
from atcodertools.models.predictor.format_prediction_result import FormatPredictionResult
Expand All @@ -28,7 +29,7 @@ def __init__(self, test_dir):
def is_valid_case(self, case_name):
return os.path.isdir(self._get_test_case_dir(case_name))

def run(self, case_name: str) -> Response:
def load_problem_content(self, case_name: str) -> ProblemContent:
case_dir = self._get_test_case_dir(case_name)
format_file = os.path.join(case_dir, FORMAT_FILE_NAME)
example_files = [os.path.join(case_dir, file)
Expand All @@ -41,10 +42,14 @@ def run(self, case_name: str) -> Response:
for ex_file in example_files:
with open(ex_file, 'r') as f:
examples.append(Sample(f.read(), None))
problem_content = ProblemContent(input_format, examples)

return ProblemContent(input_format, examples)

def run(self, case_name: str) -> Response:
content = self.load_problem_content(case_name)

try:
result = FormatPredictor.predict(problem_content)
result = FormatPredictor.predict(content)
return Response(result, "OK")
except MultiplePredictionResultsError:
return Response(None, "Multiple results")
Expand Down

0 comments on commit 5d4da07

Please sign in to comment.