def download(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         return []
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = utils.SampleZipper()
     lang = None
     for pre, h3 in self._find_sample_tags(soup):
         s = utils.textfile(utils.dos2unix(pre.string.lstrip()))
         name = h3.string
         l = self._get_tag_lang(pre)
         if lang is None:
             lang = l
         elif lang != l:
             log.info(
                 'skipped due to language: current one is %s, not %s: %s ',
                 lang, l, name)
             continue
         samples.add(s, name)
     return samples.get()
 def login_with_github(self, get_credentials, session=None):
     session = session or requests.Session()
     url = 'https://yukicoder.me/auth/github'
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     if urllib.parse.urlparse(resp.url).hostname == 'yukicoder.me':
         log.info('You have already signed in.')
         return True
     # redirect to github.com
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser)
     form = soup.find('form')
     if not form:
         log.error('form not found')
         log.info('Did you logged in?')
         return False
     log.debug('form: %s', str(form))
     # post
     username, password = get_credentials()
     form = utils.FormSender(form, url=resp.url)
     form.set('login', username)
     form.set('password', password)
     resp = form.request(session)
     resp.raise_for_status()
     if urllib.parse.urlparse(resp.url).hostname == 'yukicoder.me':
         log.success('You signed in.')
         return True
     else:
         log.failure('You failed to sign in. Wrong user ID or password.')
         return False
 def login(self, get_credentials, session=None):
     session = session or requests.Session()
     url = 'https://practice.contest.atcoder.jp/login'
     # get
     log.status('GET: %s', url)
     resp = session.get(url, allow_redirects=False)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     for msg in msgs:
         log.status('message: %s', msg)
     if msgs:
         return 'login' not in resp.url
     # post
     username, password = get_credentials()
     log.status('POST: %s', url)
     resp = session.post(url,
                         data={
                             'name': username,
                             'password': password
                         },
                         allow_redirects=False)
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     AtCoderService._report_messages(msgs)
     return 'login' not in resp.url  # AtCoder redirects to the top page if success
 def download(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = utils.SampleZipper()
     for pre in soup.find_all('pre'):
         log.debug('pre: %s', str(pre))
         hn = utils.previous_sibling_tag(pre)
         log.debug('hN: %s', str(hn))
         log.debug(hn)
         if hn and hn.name in [
                 'h2', 'h3'
         ] and hn.string and 'ample' in hn.string.lower(
         ):  # 'ample' is the suffix of 'sample', 'example'
             s = utils.textfile(pre.string.lstrip())
             name = hn.string
             samples.add(s, name)
     return samples.get()
 def submit(self, code, language, session=None):
     assert language in self.get_language_dict(session=session)
     session = session or requests.Session()
     url = self.get_url() + '/submit'
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser)
     form = soup.find('form', action=re.compile(r'/submit$'))
     if not form:
         log.error('form not found')
         return None
     log.debug('form: %s', str(form))
     # post
     form = utils.FormSender(form, url=resp.url)
     if False:
         form.set('source', code)
     else:
         form.set_file('file', ('source', code))
     form.set('lang', language)
     resp = form.request(session=session)
     resp.raise_for_status()
     # result
     if '/submissions/' in resp.url:
         log.success('success: result: %s', resp.url)
         return resp.url
     else:
         log.failure('failure')
         return None
 def download(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = utils.SampleZipper()
     for tag in soup.find_all('div', class_=re.compile(
             '^(in|out)put$')):  # Codeforces writes very nice HTML :)
         log.debug('tag: %s', str(tag))
         assert len(list(tag.children))
         title, pre = list(tag.children)
         assert 'title' in title.attrs['class']
         assert pre.name == 'pre'
         s = ''
         for it in pre.children:
             if it.name == 'br':
                 s += '\n'
             else:
                 s += it.string
         samples.add(s, title.string)
     return samples.get()
 def login(self, get_credentials, session=None):
     session = session or requests.Session()
     url = 'http://codeforces.com/enter'
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     if resp.url != url:  # redirected
         log.info('You have already signed in.')
         return True
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     form = soup.find('form', id='enterForm')
     log.debug('form: %s', str(form))
     username, password = get_credentials()
     form = utils.FormSender(form, url=resp.url)
     form.set('handle', username)
     form.set('password', password)
     form.set('remember', 'on')
     # post
     resp = form.request(session)
     resp.raise_for_status()
     if resp.url != url:  # redirected
         log.success('Welcome, %s.', username)
         return True
     else:
         log.failure('Invalid handle or password.')
         return False
 def get_input_format(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser)
     for h4 in soup.find_all('h4'):
         if h4.string == '入力':
             return h4.parent.find('pre').string
 def download(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = utils.SampleZipper()
     for h2 in soup.find_all('h2'):
         it = self._parse_sample_tag(h2)
         if it is not None:
             s, name = it
             samples.add(s, name)
     return samples.get()
 def download_all(self, session=None):
     session = session or requests.Session()
     url = 'http://yukicoder.me/problems/no/{}/testcase.zip'.format(self.problem_no)
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     # parse
     samples = collections.defaultdict(list)
     with zipfile.ZipFile(io.BytesIO(resp.content)) as fh:
         for filename in sorted(fh.namelist()):  # "test_in" < "test_out"
             s = fh.read(filename).decode()
             name = os.path.basename(filename)
             if os.path.splitext(name)[1] == '.in':  # ".in" extension is confusing
                 name = os.path.splitext(name)[0]
             print(filename, name)
             samples[os.path.basename(filename)] += [( s, name )]
     return sorted(samples.values())
 def get_input_format(self, session=None):
     session = session or requests.Session()
     url = self.get_url()
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         return ''
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     for h3 in soup.find_all('h3'):
         if h3.string == '入力':
             s = ''
             for it in h3.parent.find('pre'):
                 s += it.string or it  # AtCoder uses <var>...</var> for math symbols
             return s
 def _get_task_id(self, session=None):
     if self._task_id is None:
         session = session or requests.Session()
         url = self.get_url()
         # get
         log.status('GET: %s', url)
         resp = session.get(url)
         log.status(utils.describe_status_code(resp.status_code))
         resp.raise_for_status()
         msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
         if AtCoderService._report_messages(msgs, unexpected=True):
             return {}
         # parse
         soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                  utils.html_parser)
         submit = soup.find('a', href=re.compile(r'^/submit\?task_id='))
         if not submit:
             log.error('link to submit not found')
             return False
         m = re.match(r'^/submit\?task_id=([0-9]+)$', submit.attrs['href'])
         assert m
         self._task_id = int(m.group(1))
     return self._task_id
 def get_language_dict(self, session=None):
     session = session or requests.Session()
     url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id)
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         return {}
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     select = soup.find(
         'select', class_='submit-language-selector'
     )  # NOTE: AtCoder can vary languages depending on tasks, even in one contest. here, ignores this fact.
     language_dict = {}
     for option in select.find_all('option'):
         language_dict[option.attrs['value']] = {
             'description': option.string
         }
     return language_dict
 def submit(self, code, language, session=None):
     assert language in self.get_language_dict(session=session)
     session = session or requests.Session()
     url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id)
     # get
     log.status('GET: %s', url)
     resp = session.get(url)
     log.status(utils.describe_status_code(resp.status_code))
     resp.raise_for_status()
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         return None
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     form = soup.find('form', action=re.compile(r'^/submit\?task_id='))
     if not form:
         log.error('form not found')
         return None
     log.debug('form: %s', str(form))
     # post
     task_id = self._get_task_id(session=session)
     form = utils.FormSender(form, url=resp.url)
     form.set('task_id', str(task_id))
     form.set('source_code', code)
     form.set('language_id_{}'.format(task_id), language)
     resp = form.request(session=session)
     resp.raise_for_status()
     # result
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     AtCoderService._report_messages(msgs)
     if '/submissions/me' in resp.url:
         log.success('success: result: %s', resp.url)
         return resp.url
     else:
         log.failure('failure')
         return None