3
3
import os
4
4
import re
5
5
from http .cookiejar import LWPCookieJar
6
- from typing import List , Optional
6
+ from typing import List , Optional , Tuple
7
7
8
8
import requests
9
9
from bs4 import BeautifulSoup
10
10
11
11
from atcodertools .models .contest import Contest
12
12
from atcodertools .models .problem import Problem
13
13
from atcodertools .models .problem_content import ProblemContent , InputFormatDetectionError , SampleDetectionError
14
+ from atcodertools .models .submission import Submission
14
15
15
16
16
17
class LoginError (Exception ):
@@ -50,6 +51,12 @@ def __call__(cls, *args, **kwargs):
50
51
return cls ._instances [cls ]
51
52
52
53
54
+ def default_credential_supplier () -> Tuple [str , str ]:
55
+ username = input ('AtCoder username: ' )
56
+ password = getpass .getpass ('AtCoder password: ' )
57
+ return username , password
58
+
59
+
53
60
class AtCoderClient (metaclass = Singleton ):
54
61
55
62
def __init__ (self ):
@@ -60,7 +67,14 @@ def check_logging_in(self):
60
67
resp = self ._request (private_url )
61
68
return resp .url == private_url
62
69
63
- def login (self , username = None , password = None , use_local_session_cache = True , save_session_cache = True ):
70
+ def login (self ,
71
+ credential_supplier = None ,
72
+ use_local_session_cache = True ,
73
+ save_session_cache = True ):
74
+
75
+ if credential_supplier is None :
76
+ credential_supplier = default_credential_supplier
77
+
64
78
if use_local_session_cache :
65
79
load_cookie_to (self ._session )
66
80
if self .check_logging_in ():
@@ -71,11 +85,7 @@ def login(self, username=None, password=None, use_local_session_cache=True, save
71
85
72
86
return
73
87
74
- if username is None :
75
- username = input ('AtCoder username: ' )
76
-
77
- if password is None :
78
- password = getpass .getpass ('AtCoder password: ' )
88
+ username , password = credential_supplier ()
79
89
80
90
resp = self ._request ("https://arc001.contest.atcoder.jp/login" , data = {
81
91
'name' : username ,
@@ -131,31 +141,44 @@ def download_all_contests(self) -> List[Contest]:
131
141
contest_ids = sorted (contest_ids )
132
142
return [Contest (contest_id ) for contest_id in contest_ids ]
133
143
134
- def submit_source_code (self , contest : Contest , problem : Problem , lang , source ):
135
- resp = self ._request (contest .submission_url ())
144
+ def submit_source_code (self , contest : Contest , problem : Problem , lang : str , source : str ) -> Submission :
145
+ resp = self ._request (contest .get_submit_url ())
146
+
136
147
soup = BeautifulSoup (resp .text , "html.parser" )
137
148
session_id = soup .find ("input" , attrs = {"type" : "hidden" }).get ("value" )
138
149
task_select_area = soup .find (
139
150
'select' , attrs = {"id" : "submit-task-selector" })
140
151
task_field_name = task_select_area .get ("name" )
141
152
task_number = task_select_area .find (
142
153
"option" , text = re .compile ('{} -' .format (problem .get_alphabet ()))).get ("value" )
143
-
144
154
language_select_area = soup .find (
145
155
'select' , attrs = {"id" : "submit-language-selector-{}" .format (task_number )})
146
156
language_field_name = language_select_area .get ("name" )
147
157
language_number = language_select_area .find (
148
- "option" , text = re . compile ( lang ) ).get ("value" )
158
+ "option" , text = lang ).get ("value" )
149
159
postdata = {
150
160
"__session" : session_id ,
151
161
task_field_name : task_number ,
152
162
language_field_name : language_number ,
153
163
"source_code" : source
154
164
}
155
- self ._request (
156
- contest .get_url (),
165
+ resp = self ._request (
166
+ contest .get_submit_url (),
157
167
data = postdata ,
158
168
method = 'POST' )
169
+ return Submission .make_submissions_from (resp .text )[0 ]
170
+
171
+ def download_submission_list (self , contest : Contest ) -> List [Submission ]:
172
+ submissions = []
173
+ page_num = 1
174
+ while True :
175
+ resp = self ._request (contest .get_my_submissions_url (page_num ))
176
+ new_submissions = Submission .make_submissions_from (resp .text )
177
+ if len (new_submissions ) == 0 :
178
+ break
179
+ submissions += new_submissions
180
+ page_num += 1
181
+ return submissions
159
182
160
183
def _request (self , url : str , method = 'GET' , ** kwargs ):
161
184
if method == 'GET' :
0 commit comments