kattis-cli 1.0.7__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kattis_cli/client.py +464 -0
- kattis_cli/download.py +196 -145
- kattis_cli/fireworks.py +119 -0
- kattis_cli/kattis.py +68 -412
- kattis_cli/kattis_setup.py +124 -87
- kattis_cli/main.py +3 -3
- kattis_cli/solution_tester.py +221 -0
- kattis_cli/ui.py +112 -71
- kattis_cli/utils/languages.py +11 -5
- kattis_cli/utils/utility.py +2 -0
- {kattis_cli-1.0.7.dist-info → kattis_cli-1.1.1.dist-info}/METADATA +28 -20
- kattis_cli-1.1.1.dist-info/RECORD +21 -0
- {kattis_cli-1.0.7.dist-info → kattis_cli-1.1.1.dist-info}/WHEEL +1 -1
- kattis_cli/test_solution.py +0 -179
- kattis_cli-1.0.7.dist-info/RECORD +0 -19
- {kattis_cli-1.0.7.dist-info → kattis_cli-1.1.1.dist-info}/entry_points.txt +0 -0
- {kattis_cli-1.0.7.dist-info → kattis_cli-1.1.1.dist-info/licenses}/LICENSE +0 -0
kattis_cli/ui.py
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"""User interface for the Kattis CLI.
|
|
2
|
+
|
|
3
|
+
This module exposes a UIManager that renders problem metadata and a
|
|
4
|
+
module-level `show_problem_metadata` function delegating to a default
|
|
5
|
+
UIManager instance for backward compatibility.
|
|
2
6
|
"""
|
|
3
7
|
|
|
4
|
-
from typing import Any, Dict
|
|
8
|
+
from typing import Any, Dict, Optional, Protocol
|
|
5
9
|
from rich.console import Console
|
|
6
10
|
from rich.table import Table
|
|
7
11
|
from rich import box
|
|
@@ -10,76 +14,113 @@ from . import download
|
|
|
10
14
|
from . import settings
|
|
11
15
|
|
|
12
16
|
|
|
17
|
+
class UIManager:
|
|
18
|
+
"""Handles UI rendering tasks (currently: problem metadata)."""
|
|
19
|
+
|
|
20
|
+
class DownloadManagerLike(Protocol):
|
|
21
|
+
"""Protocol describing the minimal download manager API used here."""
|
|
22
|
+
|
|
23
|
+
def load_problem_metadata(self, problemid: str = '') -> Dict[Any, Any]:
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
download_manager: Optional["UIManager.DownloadManagerLike"] = None,
|
|
29
|
+
) -> None:
|
|
30
|
+
# Accept a download manager for dependency injection; fall back to
|
|
31
|
+
# the module-level functions in `download` for compatibility.
|
|
32
|
+
# Use structural typing (Protocol) so both the manager instance and
|
|
33
|
+
# the legacy module object satisfy the type checker.
|
|
34
|
+
self.download_manager = download_manager or download
|
|
35
|
+
|
|
36
|
+
def show_problem_metadata(self, problemid: str = '') -> Dict[Any, Any]:
|
|
37
|
+
"""Render and print metadata for a problem.
|
|
38
|
+
|
|
39
|
+
If `problemid` is provided the metadata for that problem is shown.
|
|
40
|
+
If omitted, the method attempts to find a problem folder in the
|
|
41
|
+
current working directory and show its metadata.
|
|
42
|
+
|
|
43
|
+
Returns the metadata dictionary as loaded from disk or an empty
|
|
44
|
+
dict when no metadata is available.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
console = Console()
|
|
48
|
+
metadata = self.download_manager.load_problem_metadata(problemid)
|
|
49
|
+
if metadata:
|
|
50
|
+
table = Table(
|
|
51
|
+
title=f"[not italic bold blue]{metadata['title']}[/]")
|
|
52
|
+
table.box = box.SQUARE
|
|
53
|
+
Align.center(table)
|
|
54
|
+
table.add_column(
|
|
55
|
+
"Problem ID",
|
|
56
|
+
justify="center",
|
|
57
|
+
style="cyan",
|
|
58
|
+
no_wrap=False)
|
|
59
|
+
table.add_column(
|
|
60
|
+
"Difficulty",
|
|
61
|
+
justify="center",
|
|
62
|
+
style="cyan",
|
|
63
|
+
no_wrap=False)
|
|
64
|
+
table.add_column(
|
|
65
|
+
"CPU Limit",
|
|
66
|
+
justify="center",
|
|
67
|
+
style="cyan",
|
|
68
|
+
no_wrap=False)
|
|
69
|
+
table.add_column(
|
|
70
|
+
"Memory Limit",
|
|
71
|
+
justify="center",
|
|
72
|
+
style="cyan",
|
|
73
|
+
no_wrap=False)
|
|
74
|
+
table.add_column(
|
|
75
|
+
"Submissions",
|
|
76
|
+
justify="center",
|
|
77
|
+
style="cyan",
|
|
78
|
+
no_wrap=False)
|
|
79
|
+
table.add_column(
|
|
80
|
+
"Accepted",
|
|
81
|
+
justify="center",
|
|
82
|
+
style="cyan",
|
|
83
|
+
no_wrap=False)
|
|
84
|
+
|
|
85
|
+
p_id = metadata['problemid']
|
|
86
|
+
problem_link = f"[link={settings.KATTIS_PROBLEM_URL}{p_id}]"
|
|
87
|
+
problem_link += f"{p_id}[/link]"
|
|
88
|
+
table.add_row(problem_link,
|
|
89
|
+
metadata['difficulty'],
|
|
90
|
+
metadata['cpu_limit'],
|
|
91
|
+
metadata['mem_limit'],
|
|
92
|
+
str(metadata['submissions']),
|
|
93
|
+
str(metadata['accepted'])
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
console.print(table)
|
|
97
|
+
elif problemid:
|
|
98
|
+
error = "Problem metadata for problemid: [bold blue]"
|
|
99
|
+
error += f"{problemid}[/bold blue] not found."
|
|
100
|
+
console.print(error, style='red bold')
|
|
101
|
+
suggest = "Download problem metadata using: [bold blue]"
|
|
102
|
+
suggest += f"kattis get {problemid}[/bold blue]"
|
|
103
|
+
console.print(suggest, style='red bold')
|
|
104
|
+
else:
|
|
105
|
+
error = "Kattis problem folder with meta data "
|
|
106
|
+
error += "not found in current directory."
|
|
107
|
+
console.print(error, style='red bold')
|
|
108
|
+
suggest = "Download problem metadata using: [bold blue]"
|
|
109
|
+
suggest += "kattis get <problemid>[/bold blue]"
|
|
110
|
+
console.print(suggest, style='red bold')
|
|
111
|
+
|
|
112
|
+
return metadata
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# Default UI manager for module-level compatibility functions
|
|
116
|
+
_ui_manager = UIManager()
|
|
117
|
+
|
|
118
|
+
|
|
13
119
|
def show_problem_metadata(problemid: str = '') -> Dict[Any, Any]:
|
|
14
|
-
"""
|
|
120
|
+
"""Module-level convenience wrapper for :class:`UIManager`.
|
|
15
121
|
|
|
16
|
-
|
|
17
|
-
|
|
122
|
+
This keeps the original functional API working for scripts that
|
|
123
|
+
expect a `show_problem_metadata` function.
|
|
18
124
|
"""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# print('metadata', metadata)
|
|
22
|
-
if metadata:
|
|
23
|
-
table = Table(title=f"[not italic bold blue]{metadata['title']}[/]")
|
|
24
|
-
table.box = box.SQUARE
|
|
25
|
-
Align.center(table)
|
|
26
|
-
table.add_column(
|
|
27
|
-
"Problem ID",
|
|
28
|
-
justify="center",
|
|
29
|
-
style="cyan",
|
|
30
|
-
no_wrap=False)
|
|
31
|
-
table.add_column(
|
|
32
|
-
"Difficulty",
|
|
33
|
-
justify="center",
|
|
34
|
-
style="cyan",
|
|
35
|
-
no_wrap=False)
|
|
36
|
-
table.add_column(
|
|
37
|
-
"CPU Limit",
|
|
38
|
-
justify="center",
|
|
39
|
-
style="cyan",
|
|
40
|
-
no_wrap=False)
|
|
41
|
-
table.add_column(
|
|
42
|
-
"Memory Limit",
|
|
43
|
-
justify="center",
|
|
44
|
-
style="cyan",
|
|
45
|
-
no_wrap=False)
|
|
46
|
-
table.add_column(
|
|
47
|
-
"Submissions",
|
|
48
|
-
justify="center",
|
|
49
|
-
style="cyan",
|
|
50
|
-
no_wrap=False)
|
|
51
|
-
table.add_column(
|
|
52
|
-
"Accepted",
|
|
53
|
-
justify="center",
|
|
54
|
-
style="cyan",
|
|
55
|
-
no_wrap=False)
|
|
56
|
-
|
|
57
|
-
p_id = metadata['problemid']
|
|
58
|
-
problem_link = f"[link={settings.KATTIS_PROBLEM_URL}{p_id}]"
|
|
59
|
-
problem_link += f"{p_id}[/link]"
|
|
60
|
-
# console.print(sources_link)
|
|
61
|
-
table.add_row(problem_link,
|
|
62
|
-
metadata['difficulty'],
|
|
63
|
-
metadata['cpu_limit'],
|
|
64
|
-
metadata['mem_limit'],
|
|
65
|
-
str(metadata['submissions']),
|
|
66
|
-
str(metadata['accepted'])
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
console.print(table)
|
|
70
|
-
elif problemid:
|
|
71
|
-
error = "Problem metadata for problemid: [bold blue]"
|
|
72
|
-
error += f"{problemid}[/bold blue] not found."
|
|
73
|
-
console.print(error, style='red bold')
|
|
74
|
-
suggest = "Download problem metadata using: [bold blue]"
|
|
75
|
-
suggest += f"kattis get {problemid}[/bold blue]"
|
|
76
|
-
console.print(suggest, style='red bold')
|
|
77
|
-
else:
|
|
78
|
-
error = "Kattis problem folder with meta data "
|
|
79
|
-
error += "not found in current directory."
|
|
80
|
-
console.print(error, style='red bold')
|
|
81
|
-
suggest = "Download problem metadata using: [bold blue]"
|
|
82
|
-
suggest += "kattis get <problemid>[/bold blue]"
|
|
83
|
-
console.print(suggest, style='red bold')
|
|
84
|
-
|
|
85
|
-
return metadata
|
|
125
|
+
|
|
126
|
+
return _ui_manager.show_problem_metadata(problemid)
|
kattis_cli/utils/languages.py
CHANGED
|
@@ -13,6 +13,8 @@ from kattis_cli.utils.utility import find_problem_root_folder
|
|
|
13
13
|
|
|
14
14
|
LANGUAGE_GUESS = {
|
|
15
15
|
'.c': 'c',
|
|
16
|
+
'.h': 'c',
|
|
17
|
+
'.hpp': 'cpp',
|
|
16
18
|
'.c++': 'cpp',
|
|
17
19
|
'.cc': 'cpp',
|
|
18
20
|
'.c#': 'csharp',
|
|
@@ -129,6 +131,8 @@ def guess_language(ext: str, files: List[str]) -> str:
|
|
|
129
131
|
return "c"
|
|
130
132
|
else:
|
|
131
133
|
return "cpp"
|
|
134
|
+
if ext == '.hpp':
|
|
135
|
+
return "cpp"
|
|
132
136
|
if ext == ".py":
|
|
133
137
|
return "python3"
|
|
134
138
|
return LANGUAGE_GUESS.get(ext, '')
|
|
@@ -314,19 +318,21 @@ filename extension "{ext}"''')
|
|
|
314
318
|
return problemid, loc_language, mainclass, files, root_folder, lang_config
|
|
315
319
|
|
|
316
320
|
|
|
317
|
-
def get_coding_files() -> List[str]:
|
|
321
|
+
def get_coding_files(base_path: Path = Path.cwd()) -> List[str]:
|
|
318
322
|
"""Get coding files from current directory.
|
|
319
323
|
|
|
320
324
|
Returns:
|
|
321
325
|
List[str]: List of coding files.
|
|
322
326
|
"""
|
|
323
|
-
|
|
327
|
+
|
|
328
|
+
if Path(base_path / "src").is_dir():
|
|
329
|
+
base_path = base_path / "src"
|
|
324
330
|
console = Console()
|
|
325
|
-
files = [
|
|
326
|
-
|
|
331
|
+
files = [str(f) for f in base_path.rglob(
|
|
332
|
+
'*') if f.is_file() and valid_extension(str(f))]
|
|
327
333
|
if not files:
|
|
328
334
|
console.print(
|
|
329
|
-
'No source file(s) found in
|
|
335
|
+
f'No source file(s) found in {base_path}!',
|
|
330
336
|
style='bold red')
|
|
331
337
|
exit(1)
|
|
332
338
|
return files
|
kattis_cli/utils/utility.py
CHANGED
|
@@ -34,6 +34,8 @@ def find_problem_root_folder(
|
|
|
34
34
|
Returns:
|
|
35
35
|
bool: True if path exists, False otherwise
|
|
36
36
|
"""
|
|
37
|
+
if filename.startswith('/'):
|
|
38
|
+
filename = Path(filename).name
|
|
37
39
|
for file in path.glob(filename):
|
|
38
40
|
name, ext = os.path.splitext(file.name)
|
|
39
41
|
folder_name = path.parts[-1]
|
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kattis-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: A command-line tool for Kattis
|
|
5
|
-
|
|
5
|
+
License-File: LICENSE
|
|
6
6
|
Author: Ram Basnet
|
|
7
7
|
Author-email: rbasnet@coloradomesa.edu
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.10.0,<4.0.0
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
17
|
Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
|
|
18
18
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
19
|
-
Requires-Dist: lxml (>=
|
|
19
|
+
Requires-Dist: lxml (>=6.0.1,<7.0.0)
|
|
20
20
|
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
21
21
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
22
22
|
Requires-Dist: rich (>=13.6.0,<14.0.0)
|
|
23
23
|
Requires-Dist: tomlkit (>=0.12.2,<0.13.0)
|
|
24
24
|
Requires-Dist: trogon (>=0.6.0,<0.7.0)
|
|
25
|
-
Project-URL:
|
|
25
|
+
Project-URL: Bug Tracker, https://github.com/rambasnet/kattis-cli/issues
|
|
26
|
+
Project-URL: Homepage, https://github.com/rambasnet/kattis-cli
|
|
26
27
|
Description-Content-Type: text/markdown
|
|
27
28
|
|
|
28
29
|
# Kattis-CLI
|
|
29
30
|
|
|
30
|
-
Kattis CLI - download, test and submit Kattis problems using CLI.
|
|
31
|
+
Kattis CLI - download, test and submit Kattis problems using CLI or TUI.
|
|
31
32
|
Inspired by the official Kattis CLI: [https://github.com/Kattis/kattis-cli](https://github.com/Kattis/kattis-cli)
|
|
32
33
|
|
|
33
34
|

|
|
@@ -35,6 +36,10 @@ Inspired by the official Kattis CLI: [https://github.com/Kattis/kattis-cli](http
|
|
|
35
36
|
[](https://pypi.org/project/kattis-cli/)
|
|
36
37
|
[](https://pypi.org/project/kattis-cli/)
|
|
37
38
|
|
|
39
|
+
## Quick Tour of Kattis-CLI
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
38
43
|
## Requirements
|
|
39
44
|
|
|
40
45
|
- Python 3.8+ (PyPy preferred as Kattis uses PyPy to run your Python3 solutions)
|
|
@@ -44,7 +49,7 @@ Inspired by the official Kattis CLI: [https://github.com/Kattis/kattis-cli](http
|
|
|
44
49
|
|
|
45
50
|
- Use Command Line or PowerShell
|
|
46
51
|
- Make sure python is in your PATH
|
|
47
|
-
|
|
52
|
+
- Install Python from Windows Store
|
|
48
53
|
- if you get codec error while running kattis-cli, run the following command in Command Prompt:
|
|
49
54
|
|
|
50
55
|
```bash
|
|
@@ -56,17 +61,15 @@ chcp 65001
|
|
|
56
61
|
|
|
57
62
|
If you've Python version 3.8 or higher, you can skip creating virtual environment. If you wish to create a virtual environment, see intructions below.
|
|
58
63
|
|
|
59
|
-
|
|
60
64
|
### Create and activate virtual environment using venv
|
|
61
65
|
|
|
62
66
|
- follow the instruction provided in the link to create and activate virtual environment:
|
|
63
|
-
[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)
|
|
64
|
-
|
|
67
|
+
[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)
|
|
65
68
|
|
|
66
69
|
### Create and activate virtual environment using conda
|
|
67
70
|
|
|
68
71
|
- follow the instruction provided in the link to create and activate virtual environment:
|
|
69
|
-
[https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#activating-an-environment](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#activating-an-environment)
|
|
72
|
+
[https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#activating-an-environment](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#activating-an-environment)
|
|
70
73
|
|
|
71
74
|
## Install Kattis-cli
|
|
72
75
|
|
|
@@ -94,7 +97,6 @@ python -m pip install kattis-cli --upgrade
|
|
|
94
97
|
|
|
95
98
|
- on Windows add the path shown in the output of the above command to your PATH environment variable
|
|
96
99
|
|
|
97
|
-
|
|
98
100
|
## Kattis configuration
|
|
99
101
|
|
|
100
102
|
- run the following command and enter your Kattis credentials
|
|
@@ -143,7 +145,7 @@ kattis info
|
|
|
143
145
|
- currently the following languages have been tested: Python 3, C++, NodeJS, C, Java
|
|
144
146
|
- make sure CLI compilers are in your PATH
|
|
145
147
|
- make sure python3 files have first line shebang: !/usr/bin/env python3
|
|
146
|
-
|
|
148
|
+
- or have extensions .py3
|
|
147
149
|
- update the **.kattis-cli.toml** file in your home directory to add more languages
|
|
148
150
|
- see [kattis_cli/.kattis-cli.toml](https://github.com/rambasnet/kattis-cli/blob/main/kattis_cli/.kattis-cli.toml) file for example.
|
|
149
151
|
|
|
@@ -163,7 +165,6 @@ kattis test -a 6 # Answer accepted upto 6 decimal places of accuracy
|
|
|
163
165
|
kattis test -a 6
|
|
164
166
|
```
|
|
165
167
|
|
|
166
|
-
|
|
167
168
|
### Submit a problem
|
|
168
169
|
|
|
169
170
|
- make sure you've configured kattis-cli
|
|
@@ -185,13 +186,19 @@ kattis submit
|
|
|
185
186
|
|
|
186
187
|
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please make sure to update tests as appropriate. Adding support for more languages is highly appreciated.
|
|
187
188
|
|
|
188
|
-
|
|
189
189
|
## Using this Repo
|
|
190
190
|
|
|
191
191
|
- clone this repo
|
|
192
192
|
- create virtual environment with pypy 3.8 or higher
|
|
193
193
|
- using conda the following command creates kattis virtual environment with pypy3.8
|
|
194
194
|
|
|
195
|
+
```bash
|
|
196
|
+
git clone git@github.com:rambasnet/kattis-cli.git
|
|
197
|
+
cd kattis-cli
|
|
198
|
+
pip install poetry
|
|
199
|
+
poetry install
|
|
200
|
+
```
|
|
201
|
+
|
|
195
202
|
### Using conda and virtual environment
|
|
196
203
|
|
|
197
204
|
```bash
|
|
@@ -210,7 +217,7 @@ pip install -r requirements.txt
|
|
|
210
217
|
```bash
|
|
211
218
|
make
|
|
212
219
|
./build.sh
|
|
213
|
-
pip install dist/kattis_cli-x.x.x-py3-none-any.whl --force-reinstall
|
|
220
|
+
pip install dist/kattis_cli-x.x.x-py3-none-any.whl --force-reinstall
|
|
214
221
|
```
|
|
215
222
|
|
|
216
223
|
### Using Docker
|
|
@@ -220,6 +227,7 @@ pip install dist/kattis_cli-x.x.x-py3-none-any.whl --force-reinstall
|
|
|
220
227
|
- if using Windows, run the following command in git-bash Terminal
|
|
221
228
|
|
|
222
229
|
```bash
|
|
223
|
-
|
|
230
|
+
docker-compose up -d
|
|
231
|
+
docker exec -it kattis-cli zsh
|
|
224
232
|
```
|
|
225
233
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
kattis_cli/.kattis-cli.toml,sha256=kGh0gmpFAnivyUC9hR8Y1ZqYJeTBWNyBQ9zOg4AInZ0,898
|
|
2
|
+
kattis_cli/__init__.py,sha256=afN92pog2fGyicY6KNBofYbCBYbYj4Fpi_INUSpsc-E,402
|
|
3
|
+
kattis_cli/client.py,sha256=5ef-pq737q-VBBxY1F-bEbP9Mf8145YppL4m9NlVCVY,16938
|
|
4
|
+
kattis_cli/download.py,sha256=IFjebvvxJyPKfsK8Voo06llSsybBqqylUWEv5lF2J7o,8651
|
|
5
|
+
kattis_cli/fireworks.py,sha256=yKFXIvDDdNrzBhpEt2Pdy5zgfYjJffoOEf2yUFlu2TQ,4134
|
|
6
|
+
kattis_cli/kattis.py,sha256=wpnM6sC0a32kJYzEux27izug59bicexNnOFxcx0qWM8,2621
|
|
7
|
+
kattis_cli/kattis_setup.py,sha256=mic79GjOI_rC6Lfl5D5ORDMWdrcxR71ksYUM51yezu8,5659
|
|
8
|
+
kattis_cli/main.py,sha256=NoSSGZdtd3PO3TnAIi5stvTi8Zb_6Ppd9pLKv6CiYKE,4511
|
|
9
|
+
kattis_cli/settings.py,sha256=d5q4dYj9VqDSqPalleh2oZWtND-1bPB0T2IwdajFrBg,591
|
|
10
|
+
kattis_cli/solution_tester.py,sha256=hTXtryYs8lkO9CkSPtQNjhrAPPLaC4au5ueCQ3ioZWQ,7577
|
|
11
|
+
kattis_cli/ui.py,sha256=2qFWz9QB7cgjLfZKHrWUrKFVYLRLwl0c37ZTNljwmAI,4580
|
|
12
|
+
kattis_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
kattis_cli/utils/config.py,sha256=6SIuiXA9sFADo8RZUj8A6rXb3uqmrWrmmArfZrqNQdw,2293
|
|
14
|
+
kattis_cli/utils/languages.py,sha256=gcJJJwkPS1Zpg76atwoo2O2Vd7ETKBQV-KD_cwclrmE,8928
|
|
15
|
+
kattis_cli/utils/run_program.py,sha256=NWQ6vtTeWgkaW75r91FIHGXR5cAbeu8yMb5hwzpYFsg,2613
|
|
16
|
+
kattis_cli/utils/utility.py,sha256=oUbydPbcC2wXvfku21YAWpaJjuBKaBRVybMAWCSfM9Y,2987
|
|
17
|
+
kattis_cli-1.1.1.dist-info/METADATA,sha256=TLE1BHoCDFfWPj0eKEQG4gk4F0ciOBROwlkG7_FnVcs,6962
|
|
18
|
+
kattis_cli-1.1.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
19
|
+
kattis_cli-1.1.1.dist-info/entry_points.txt,sha256=kyzGN20VqUPR_H0J_jJUKT-10-cAMFLVegQ6C7tbHss,47
|
|
20
|
+
kattis_cli-1.1.1.dist-info/licenses/LICENSE,sha256=JmBa4SEKBCDWEgiOZcISU4tUCpli6xSpVlSYgkBXSNQ,1067
|
|
21
|
+
kattis_cli-1.1.1.dist-info/RECORD,,
|
kattis_cli/test_solution.py
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
"""Tester module for Kattis.
|
|
2
|
-
"""
|
|
3
|
-
|
|
4
|
-
from typing import Any, List, Dict
|
|
5
|
-
from math import inf
|
|
6
|
-
import glob
|
|
7
|
-
import time
|
|
8
|
-
import os
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
from rich.console import Console
|
|
11
|
-
from rich.table import Table
|
|
12
|
-
# from rich import print
|
|
13
|
-
from rich.live import Live
|
|
14
|
-
from rich.align import Align
|
|
15
|
-
from rich import box
|
|
16
|
-
from rich.prompt import Confirm
|
|
17
|
-
from rich.markup import escape
|
|
18
|
-
|
|
19
|
-
from kattis_cli import kattis
|
|
20
|
-
from kattis_cli.utils import languages, run_program, utility
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_samples(
|
|
24
|
-
problemid: str,
|
|
25
|
-
loc_language: str,
|
|
26
|
-
mainclass: str,
|
|
27
|
-
problem_root_folder: str,
|
|
28
|
-
files: List[str],
|
|
29
|
-
lang_config: Dict[Any, Any],
|
|
30
|
-
accuracy: float = inf
|
|
31
|
-
) -> None:
|
|
32
|
-
"""Tests a problem by running all the .in files in
|
|
33
|
-
the problem folder and comparing the output to the .ans files.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
problem (str): problemid
|
|
37
|
-
loc_language (str): programming language
|
|
38
|
-
mainclass (str): main class
|
|
39
|
-
problem_root_folder (str): root folder where this problem is located
|
|
40
|
-
files (List[str]): List of files
|
|
41
|
-
lang_config (Dict[Any, Any]): language config
|
|
42
|
-
"""
|
|
43
|
-
console = Console()
|
|
44
|
-
# print(f"Main file: {mainfile}")
|
|
45
|
-
# config_data = config.parse_config(language)
|
|
46
|
-
|
|
47
|
-
# console.print(extensions)
|
|
48
|
-
# UI Table Header ---
|
|
49
|
-
|
|
50
|
-
table = Table(show_header=True,
|
|
51
|
-
header_style="bold blue",
|
|
52
|
-
show_lines=True,
|
|
53
|
-
show_footer=False)
|
|
54
|
-
table.box = box.SQUARE
|
|
55
|
-
table_centered = Align.center(table)
|
|
56
|
-
|
|
57
|
-
# console.print(table)
|
|
58
|
-
# Find all .in files in the problem folder
|
|
59
|
-
sep = os.path.sep
|
|
60
|
-
in_files = glob.glob(f"{problem_root_folder}{sep}data{sep}*.in")
|
|
61
|
-
if not in_files:
|
|
62
|
-
console.print(f"Sample data folder: {problem_root_folder}{sep}data",
|
|
63
|
-
style="bold blue")
|
|
64
|
-
console.print("No sample input files found!", style="bold red")
|
|
65
|
-
exit(1)
|
|
66
|
-
in_files.sort()
|
|
67
|
-
# check if language needs to be compiled
|
|
68
|
-
if lang_config['compile']:
|
|
69
|
-
ex_code, ans, error = run_program.compile_program(lang_config, files)
|
|
70
|
-
if ex_code != 0: # compilation error; exit code
|
|
71
|
-
console.print(escape(error), style='bold red')
|
|
72
|
-
exit(1)
|
|
73
|
-
# mainfile = './a.out'
|
|
74
|
-
console.print('Compiled successfully!', style='bold green')
|
|
75
|
-
# console.print(in_files)
|
|
76
|
-
count = 0
|
|
77
|
-
total = len(in_files)
|
|
78
|
-
console.clear()
|
|
79
|
-
title = f"[not italic bold blue]👷 Testing {mainclass} "
|
|
80
|
-
title += f" using {loc_language} 👷[/]"
|
|
81
|
-
table.title = title
|
|
82
|
-
with Live(table_centered, console=console,
|
|
83
|
-
screen=False, refresh_per_second=10):
|
|
84
|
-
# with beat(10):
|
|
85
|
-
# with beat(10):
|
|
86
|
-
table.add_column(
|
|
87
|
-
"Input File",
|
|
88
|
-
justify="center",
|
|
89
|
-
style="cyan",
|
|
90
|
-
no_wrap=False)
|
|
91
|
-
table.add_column(
|
|
92
|
-
"Sample Input",
|
|
93
|
-
justify="left",
|
|
94
|
-
style="cyan",
|
|
95
|
-
no_wrap=False)
|
|
96
|
-
table.add_column(
|
|
97
|
-
"Output File",
|
|
98
|
-
justify="center",
|
|
99
|
-
style="cyan",
|
|
100
|
-
no_wrap=False)
|
|
101
|
-
table.add_column(
|
|
102
|
-
"Expected Output",
|
|
103
|
-
justify="left",
|
|
104
|
-
style="cyan",
|
|
105
|
-
no_wrap=False)
|
|
106
|
-
table.add_column(
|
|
107
|
-
"Program Output",
|
|
108
|
-
justify="left",
|
|
109
|
-
style="cyan",
|
|
110
|
-
no_wrap=False)
|
|
111
|
-
table.add_column(
|
|
112
|
-
"Result",
|
|
113
|
-
justify="center",
|
|
114
|
-
style="cyan",
|
|
115
|
-
no_wrap=True)
|
|
116
|
-
|
|
117
|
-
for in_file in in_files:
|
|
118
|
-
with open(in_file, 'rb') as f:
|
|
119
|
-
input_content = f.read()
|
|
120
|
-
input_content.replace(b'\r\n', b'\n') # Windows fix
|
|
121
|
-
out_file = in_file.replace('.in', '.ans')
|
|
122
|
-
try:
|
|
123
|
-
with open(out_file, 'rb') as f:
|
|
124
|
-
expected = f.read()
|
|
125
|
-
expected.replace(b'\r\n', b'\n')
|
|
126
|
-
except FileNotFoundError:
|
|
127
|
-
try:
|
|
128
|
-
out_file = in_file.replace('.in', '.out')
|
|
129
|
-
with open(out_file, 'rb') as f:
|
|
130
|
-
expected = f.read()
|
|
131
|
-
expected.replace(b'\r\n', b'\n')
|
|
132
|
-
except FileNotFoundError:
|
|
133
|
-
expected = b"No .ans or .out file found!"
|
|
134
|
-
# Run the program
|
|
135
|
-
code, ans, error = run_program.run(lang_config, mainclass, in_file)
|
|
136
|
-
if code != 0:
|
|
137
|
-
ans = error
|
|
138
|
-
# console.print(f"{ans=} {error=}")
|
|
139
|
-
|
|
140
|
-
# floating point comparison
|
|
141
|
-
if utility.check_answer(expected.decode('utf-8'),
|
|
142
|
-
ans, accuracy):
|
|
143
|
-
result = "[bold green]✅[/bold green]"
|
|
144
|
-
count += 1
|
|
145
|
-
else:
|
|
146
|
-
result = "[bold red]❌[/bold red]"
|
|
147
|
-
|
|
148
|
-
# UI Table Row ---
|
|
149
|
-
in_filename = Path(in_file).parts[-1]
|
|
150
|
-
out_filename = Path(out_file).parts[-1]
|
|
151
|
-
# with beat(10):
|
|
152
|
-
time.sleep(0.1)
|
|
153
|
-
table.add_row(in_filename,
|
|
154
|
-
input_content.decode('utf-8'),
|
|
155
|
-
out_filename,
|
|
156
|
-
escape(expected.decode('utf-8')),
|
|
157
|
-
escape(ans),
|
|
158
|
-
result)
|
|
159
|
-
if code != 0 and 'SyntaxError: ' in error:
|
|
160
|
-
table.columns[4].style = 'bold red'
|
|
161
|
-
break
|
|
162
|
-
|
|
163
|
-
console.print(
|
|
164
|
-
f"Sample data folder: {problem_root_folder}{sep}data",
|
|
165
|
-
style="bold blue")
|
|
166
|
-
console.print(f'Total {total} input/output sample(s) found.')
|
|
167
|
-
console.print(f"{count}/{total} tests passed.")
|
|
168
|
-
if count < total:
|
|
169
|
-
console.print("Check the output columns for differences.")
|
|
170
|
-
console.print("Keep trying!")
|
|
171
|
-
else:
|
|
172
|
-
console.print(
|
|
173
|
-
"Awesome... Time to submit it to :cat: Kattis! :cat:",
|
|
174
|
-
style="bold green")
|
|
175
|
-
if Confirm.ask("Submit to Kattis?", default=True):
|
|
176
|
-
kat_language = languages.LOCAL_TO_KATTIS.get(loc_language, '')
|
|
177
|
-
kattis.submit_solution(files, problemid,
|
|
178
|
-
kat_language, mainclass,
|
|
179
|
-
tag="", force=True)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
kattis_cli/.kattis-cli.toml,sha256=kGh0gmpFAnivyUC9hR8Y1ZqYJeTBWNyBQ9zOg4AInZ0,898
|
|
2
|
-
kattis_cli/__init__.py,sha256=afN92pog2fGyicY6KNBofYbCBYbYj4Fpi_INUSpsc-E,402
|
|
3
|
-
kattis_cli/download.py,sha256=kvUJdqRW3_ETvTd4XMruEs87RWPVHp_3a4VUhcYZEz8,5863
|
|
4
|
-
kattis_cli/kattis.py,sha256=uZct7vjbEW2HA5FJr1ItSZ-b07P9JQHv5SccV4Pqjo8,13771
|
|
5
|
-
kattis_cli/kattis_setup.py,sha256=rq_-Fz8oafxFJ8MOcxJqHQT8-bezgVHZXY2hm4EQF3U,4357
|
|
6
|
-
kattis_cli/main.py,sha256=6IbGvH9NPhkdFsqkpwDMh8gQxgddnGoClulkDc-FKU8,4505
|
|
7
|
-
kattis_cli/settings.py,sha256=d5q4dYj9VqDSqPalleh2oZWtND-1bPB0T2IwdajFrBg,591
|
|
8
|
-
kattis_cli/test_solution.py,sha256=6lXaj9V5Vhfw95OywVls3Ekv86OvSYDrWI-s29YBdpk,6190
|
|
9
|
-
kattis_cli/ui.py,sha256=dI06yncjm8sdLQkupPxGRODvQ6Gbawwuqn-67FrWg6I,2682
|
|
10
|
-
kattis_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
kattis_cli/utils/config.py,sha256=6SIuiXA9sFADo8RZUj8A6rXb3uqmrWrmmArfZrqNQdw,2293
|
|
12
|
-
kattis_cli/utils/languages.py,sha256=wlhl1Zng0gQAtsWW6FLxdkdzqeeY_qQ94wqa3NLypEU,8758
|
|
13
|
-
kattis_cli/utils/run_program.py,sha256=NWQ6vtTeWgkaW75r91FIHGXR5cAbeu8yMb5hwzpYFsg,2613
|
|
14
|
-
kattis_cli/utils/utility.py,sha256=iPmfsHi-DwYxP9mKU_VurNnLJXf0dngwYPxUdqckgYo,2907
|
|
15
|
-
kattis_cli-1.0.7.dist-info/LICENSE,sha256=JmBa4SEKBCDWEgiOZcISU4tUCpli6xSpVlSYgkBXSNQ,1067
|
|
16
|
-
kattis_cli-1.0.7.dist-info/METADATA,sha256=8Ztx76NVdqgTekuwnQc6RRlkU904psIg50kehrjDpLs,6689
|
|
17
|
-
kattis_cli-1.0.7.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
18
|
-
kattis_cli-1.0.7.dist-info/entry_points.txt,sha256=kyzGN20VqUPR_H0J_jJUKT-10-cAMFLVegQ6C7tbHss,47
|
|
19
|
-
kattis_cli-1.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|