Beispiel #1
0
 def login(self,
           get_credentials: onlinejudge.type.CredentialsProvider,
           session: Optional[requests.Session] = None) -> None:
     """
     :raises LoginError:
     """
     session = session or utils.new_default_session()
     url = 'https://codeforces.com/enter'
     # get
     resp = utils.request('GET', url, session=session)
     if resp.url != url:  # redirected
         log.info('You have already signed in.')
         return
     # 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('handleOrEmail', 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)
     else:
         log.failure('Invalid handle or password.')
         raise LoginError('Invalid handle or password.')
def generate_scanner(args: 'argparse.Namespace') -> None:
    if not args.silent:
        log.warning('This feature is ' + log.red('experimental') + '.')
    if args.silent:
        for handler in log.logger.handlers:
            log.removeHandler(handler)
    problem = onlinejudge.dispatch.problem_from_url(args.url)
    if problem is None:
        sys.exit(1)
    with utils.with_cookiejar(utils.new_default_session(),
                              path=args.cookie) as sess:
        it = problem.get_input_format(session=sess)  # type: Any
    if not it:
        log.error('input format not found')
        sys.exit(1)
    try:
        log.debug('original data: %s', repr(it))
        it = list(tokenize(it))
        log.debug('tokenized: %s', str(it))
        it = list(parse(it))
        log.debug('parsed: %s', str(it))
        it = postprocess(it)
        log.debug('postprocessed: %s', str(it))
        it = export(it, use_scanf=args.scanf, repeat_macro=args.repeat_macro)
        log.debug('result: %s', repr(it))
    except:
        log.error('something wrong')
        raise
    log.success('success:')
    print(log.bold(it.rstrip()))  # to stdout
Beispiel #3
0
 def download_sample_cases(
     self,
     session: Optional[requests.Session] = None
 ) -> List[onlinejudge.type.TestCase]:
     session = session or utils.new_default_session()
     # get
     resp = utils.request('GET', self.get_url(), session=session)
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = onlinejudge._implementation.testcase_zipper.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
         s = s.lstrip()
         samples.add(s.encode(), title.string)
     return samples.get()
 def get_available_languages(
         self,
         session: Optional[requests.Session] = None) -> List[Language]:
     """
     :raises NotLoggedInError:
     """
     session = session or utils.new_default_session()
     # get
     url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id)
     resp = _request('GET', url, session=session)
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         return []
     # check whether logged in
     path = utils.normpath(urllib.parse.urlparse(resp.url).path)
     if path.startswith('/login'):
         log.error('not logged in')
         raise NotLoggedInError
     # 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.
     languages = []  # type: List[Language]
     for option in select.find_all('option'):
         languages += [Language(option.attrs['value'], option.string)]
     return languages
    def login(self,
              get_credentials: onlinejudge.type.CredentialsProvider,
              session: Optional[requests.Session] = None) -> None:
        """
        :raises LoginError:
        """

        session = session or utils.new_default_session()
        url = 'https://practice.contest.atcoder.jp/login'
        # get
        resp = _request('GET', url, session=session, allow_redirects=False)
        msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
        for msg in msgs:
            log.status('message: %s', msg)
        if msgs:
            if 'login' not in resp.url:
                return  # redirect means that you are already logged in
            else:
                raise LoginError('something wrong: ' + str(msgs))
        # post
        username, password = get_credentials()
        resp = _request('POST',
                        url,
                        session=session,
                        data={
                            'name': username,
                            'password': password
                        },
                        allow_redirects=False)
        msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
        AtCoderService._report_messages(msgs)
        if 'login' not in resp.url:
            pass  # AtCoder redirects to the top page if success
        else:
            raise LoginError('your password may be not correct: ' + str(msgs))
Beispiel #6
0
 def download_sample_cases(
     self,
     session: Optional[requests.Session] = None
 ) -> List[onlinejudge.type.TestCase]:
     session = session or utils.new_default_session()
     resp = utils.request('GET', self.get_url(), session=session)
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = utils.SampleZipper()
     for case in soup.find('table',
                           class_="samples").find('tbody').find_all('tr'):
         log.debug('case: %s', str(case))
         assert len(list(case.children))
         input_pre, output_pre = list(
             map(lambda td: td.find('pre'), list(case.children)))
         assert input_pre.name == 'pre'
         assert output_pre.name == 'pre'
         assert re.search("^preSample.*Input$", input_pre.attrs['id'])
         assert re.search("^preSample.*Output$", output_pre.attrs['id'])
         s = input_pre.get_text()
         s = s.lstrip()
         samples.add(s, "Input")
         s = output_pre.get_text()
         s = s.lstrip()
         samples.add(s, "Output")
     return samples.get()
    def _load_details(self,
                      session: Optional[requests.Session] = None) -> None:
        session = session or utils.new_default_session()

        # get
        resp = _request('GET',
                        self.get_url(type='beta', lang='ja'),
                        session=session)
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)

        # parse
        h2 = soup.find('span', class_='h2')
        self._alphabet, _, self._task_name = h2.text.partition(' - ')
        time_limit, memory_limit = h2.find_next_sibling('p').text.split(' / ')
        self._time_limit_msec = int(
            utils.remove_suffix(utils.remove_prefix(time_limit, '実行時間制限: '),
                                ' sec')) * 1000
        self._memory_limit_byte = int(
            utils.remove_suffix(utils.remove_prefix(memory_limit, 'メモリ制限: '),
                                ' MB')) * 1000 * 1000
        task_statement = soup.find('div', id='task-statement')
        p = task_statement.find('p')  # first
        if p is not None and p.text.startswith('配点 : '):
            self._score = int(
                utils.remove_suffix(utils.remove_prefix(p.text, '配点 : '),
                                    ' 点'))
        self._score_checked = True
 def download_sample_cases(
     self,
     session: Optional[requests.Session] = None
 ) -> List[onlinejudge.type.TestCase]:
     session = session or utils.new_default_session()
     # get
     resp = _request('GET', self.get_url(), session=session)
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         # example message: "message: You cannot see this page."
         log.warning('are you logged in?')
         return []
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = onlinejudge._implementation.testcase_zipper.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.encode(), name)
     return samples.get()
    def get_available_languages(
            self,
            session: Optional[requests.Session] = None) -> List[Language]:
        """
        :raises NotLoggedInError:
        """
        session = session or utils.new_default_session()

        # get
        resp = _request('GET', self.get_url(type='beta'), session=session)

        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        form = soup.find('form',
                         action='/contests/{}/submit'.format(self.contest_id))
        if form is None:
            log.error('not logged in')
            raise NotLoggedInError

        # parse
        select = form.find('div', id='select-lang').find(
            'select', attrs={'name': 'data.LanguageId'}
        )  # NOTE: AtCoder can vary languages depending on tasks, even in one contest. here, ignores this fact.
        languages = []  # type: List[Language]
        for option in select.find_all('option'):
            languages += [Language(option.attrs['value'], option.string)]
        return languages
    def _load_details(self,
                      session: Optional[requests.Session] = None,
                      lang: Optional[str] = None):
        session = session or utils.new_default_session()
        resp = _request('GET',
                        self.get_url(type='beta', lang=lang),
                        session=session)
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)

        contest_name, _, _ = soup.find('title').text.rpartition(' - ')
        contest_duration = soup.find('small', class_='contest-duration')
        self._start_time, end_time = [
            self._parse_start_time(a['href'])
            for a in contest_duration.find_all('a')
        ]
        self._duration = end_time - self._start_time
        if lang == 'en':
            self._contest_name_en = contest_name
        elif lang == 'ja':
            self._contest_name_ja = contest_name
        else:
            assert False
        _, _, self._can_participate = soup.find(
            'span',
            text=re.compile(r'^(Can Participate|参加対象): ')).text.partition(': ')
        _, _, self._rated_range = soup.find(
            'span',
            text=re.compile(r'^(Rated Range|Rated対象): ')).text.partition(': ')
        penalty_text = soup.find('span',
                                 text=re.compile(r'^(Penalty|ペナルティ): ')).text
        m = re.match(r'(Penalty|ペナルティ): (\d+)( minutes|分)', penalty_text)
        assert m
        self._penalty = datetime.timedelta(minutes=int(m.group(2)))
    def get_input_format(self,
                         session: Optional[requests.Session] = None) -> str:
        """
        :raises Exception: if no such problem exists
        """

        session = session or utils.new_default_session()

        # get
        resp = _request('GET',
                        self.get_url(type='beta'),
                        raise_for_status=False,
                        session=session)
        if _list_alert(resp):
            log.warning('are you logged in?')
        resp.raise_for_status()

        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        for h3 in soup.find_all('h3'):
            if h3.string in ('入力', 'Input'):
                tag = h3
                for _ in range(3):
                    tag = utils.next_sibling_tag(tag)
                    if tag is None:
                        break
                    if tag.name in ('pre', 'blockquote'):
                        s = ''
                        for it in tag:
                            s += it.string or it  # AtCoder uses <var>...</var> for math symbols
                        return s
        return ''
    def iterate_contests(
        self,
        lang: str = 'ja',
        session: Optional[requests.Session] = None
    ) -> Generator['AtCoderContest', None, None]:
        """
        :param lang: must be `ja` (default) or `en`.
        :note: `lang=ja` is required to see some Japanese-local contests.
        :note: You can use `lang=en` to see the English names of contests.
        """

        assert lang in ('ja', 'en')
        session = session or utils.new_default_session()
        last_page = None
        for page in itertools.count(1):  # 1-based
            if last_page is not None and page > last_page:
                break
            # get
            url = 'https://atcoder.jp/contests/archive?lang={}&page={}'.format(
                lang, page)
            resp = _request('GET', url, session=session)
            # parse
            soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                     utils.html_parser)
            if last_page is None:
                last_page = int(
                    soup.find('ul',
                              class_='pagination').find_all('li')[-1].text)
                log.debug('last page: %s', last_page)
            tbody = soup.find('tbody')
            for tr in tbody.find_all('tr'):
                yield AtCoderContest._from_table_row(tr, lang=lang)
Beispiel #13
0
 def download_sample_cases(
     self,
     session: Optional[requests.Session] = None
 ) -> List[onlinejudge.type.TestCase]:
     session = session or utils.new_default_session()
     # get
     url = self.get_url(contests=False) + '/file/statement/samples.zip'
     resp = utils.request('GET',
                          url,
                          session=session,
                          raise_for_status=False)
     if resp.status_code == 404:
         log.warning('samples.zip not found')
         log.info(
             'this 404 happens in both cases: 1. no sample cases as intended; 2. just an error'
         )
         return []
     resp.raise_for_status()
     # parse
     with zipfile.ZipFile(io.BytesIO(resp.content)) as fh:
         samples = []  # type: List[TestCase]
         for filename in sorted(fh.namelist()):
             log.debug('filename: %s', filename)
             if filename.endswith('.in'):
                 inpath = filename
                 outpath = filename[:-3] + '.ans'
                 indata = fh.read(inpath).decode()
                 outdata = fh.read(outpath).decode()
                 samples += [
                     TestCase(LabeledString(inpath, indata),
                              LabeledString(outpath, outdata))
                 ]
         return samples
Beispiel #14
0
 def is_logged_in(self, session: Optional[requests.Session] = None) -> bool:
     session = session or utils.new_default_session()
     url = 'https://toph.co/login'
     resp = utils.request('GET',
                          url,
                          session=session,
                          allow_redirects=False)
     return resp.status_code != 200
 def submit_code(self,
                 code: bytes,
                 language_id: LanguageId,
                 filename: Optional[str] = None,
                 session: Optional[requests.Session] = None) -> Submission:
     """
     :raises NotLoggedInError:
     :raises SubmissionError:
     """
     assert language_id in [
         language.id
         for language in self.get_available_languages(session=session)
     ]
     session = session or utils.new_default_session()
     # get
     url = 'http://{}.contest.atcoder.jp/submit'.format(
         self.contest_id)  # TODO: use beta.atcoder.jp
     resp = _request('GET', url, session=session)
     msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
     if AtCoderService._report_messages(msgs, unexpected=True):
         raise SubmissionError
     # check whether logged in
     path = utils.normpath(urllib.parse.urlparse(resp.url).path)
     if path.startswith('/login'):
         log.error('not logged in')
         raise NotLoggedInError
     # 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')
         raise SubmissionError
     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), str(language_id))
     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:
         # example: https://practice.contest.atcoder.jp/submissions/me#32174
         # CAUTION: this URL is not a URL of the submission
         log.success('success: result: %s', resp.url)
         # NOTE: ignore the returned legacy URL and use beta.atcoder.jp's one
         url = 'https://beta.atcoder.jp/contests/{}/submissions/me'.format(
             self.contest_id)
         return utils.DummySubmission(url, problem=self)
     else:
         log.failure('failure')
         log.debug('redirected to %s', resp.url)
         raise SubmissionError('it may be a rate limit')
Beispiel #16
0
    def get_available_languages(self, session: Optional[requests.Session] = None) -> List[Language]:
        session = session or utils.new_default_session()

        return [
            Language(LanguageId('1'), 'Java 8'),
            Language(LanguageId('3'), 'C++11'),
            Language(LanguageId('4'), 'C#'),
            Language(LanguageId('5'), 'VB'),
            Language(LanguageId('6'), 'Python 2'),
        ]
    def login_with_twitter(
            self,
            get_credentials: onlinejudge.type.CredentialsProvider,
            session: Optional[requests.Session] = None) -> None:
        """
        :raise NotImplementedError: always raised
        """

        session = session or utils.new_default_session()
        url = 'https://yukicoder.me/auth/twitter'
        raise NotImplementedError
 def is_logged_in(self,
                  session: Optional[requests.Session] = None,
                  method: Optional[str] = None) -> bool:
     session = session or utils.new_default_session()
     url = 'https://yukicoder.me/auth/github'
     resp = utils.request('GET',
                          url,
                          session=session,
                          allow_redirects=False)
     assert resp.status_code == 302
     return 'oauth' not in resp.headers['Location']
 def get_input_format(self,
                      session: Optional[requests.Session] = None
                      ) -> Optional[str]:
     session = session or utils.new_default_session()
     # get
     resp = utils.request('GET', self.get_url(), session=session)
     # 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
     return None
 def download_sample_cases(self, session: Optional[requests.Session] = None) -> List[onlinejudge.type.TestCase]:
     session = session or utils.new_default_session()
     # get
     resp = utils.request('GET', self.get_url(), session=session)
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser)
     samples = onlinejudge._implementation.testcase_zipper.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.encode(), name)
     return samples.get()
Beispiel #21
0
 def download_sample_cases(
         self,
         session: Optional[requests.Session] = None) -> List[TestCase]:
     session = session or utils.new_default_session()
     # get
     resp = utils.request('GET', self.get_url(), session=session)
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     in_pre, out_pre = soup.find_all('pre', class_='sio')
     in_p = in_pre.find_previous_sibling('p', class_='pst')
     out_p = out_pre.find_previous_sibling('p', class_='pst')
     log.debug('pre  (in): %s', in_pre.contents)
     log.debug('pre (out): %s', out_pre.contents)
     assert in_p.text.strip() == 'Sample Input'
     assert out_p.text.strip() == 'Sample Output'
     assert len(in_pre.contents) == len(out_pre.contents)
     samples = []  # type: List[TestCase]
     if len(in_pre.contents) == 1:
         assert isinstance(in_pre.contents[0], bs4.NavigableString)
         assert isinstance(out_pre.contents[0], bs4.NavigableString)
         samples += [
             TestCase(
                 'sample',
                 in_p.text.strip(),
                 in_pre.text.encode() + b'\r\n',
                 out_p.text.strip(),
                 out_pre.text.encode() + b'\r\n',
             )
         ]
     else:
         assert len(in_pre.contents) % 2 == 0
         for i in range(len(in_pre.contents) // 2):
             in_name = in_pre.contents[2 * i]
             in_data = in_pre.contents[2 * i + 1]
             out_name = out_pre.contents[2 * i]
             out_data = out_pre.contents[2 * i + 1]
             assert in_name.name == 'b'
             assert isinstance(in_data, bs4.NavigableString)
             assert out_name.name == 'b'
             assert isinstance(out_data, bs4.NavigableString)
             samples += [
                 TestCase(
                     'sample-{}'.format(i + 1),
                     in_name.text.strip(),
                     str(in_data).strip().encode() + b'\r\n',
                     out_name.text.strip(),
                     str(out_data).strip().encode() + b'\r\n',
                 )
             ]
     return samples
    def submit_code(self,
                    code: bytes,
                    language_id: LanguageId,
                    filename: Optional[str] = None,
                    session: Optional[requests.Session] = None) -> Submission:
        """
        :raises NotLoggedInError:
        :raises SubmissionError:
        """

        assert language_id in [
            language.id
            for language in self.get_available_languages(session=session)
        ]
        session = session or utils.new_default_session()

        # get
        url = 'https://atcoder.jp/contests/{}/submit'.format(self.contest_id)
        resp = _request('GET', url, session=session)

        # check whether logged in
        if 'login' in resp.url:
            raise NotLoggedInError

        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        form = soup.find('form',
                         action='/contests/{}/submit'.format(self.contest_id))
        if not form:
            raise SubmissionError('something wrong')
        log.debug('form: %s', str(form))

        # post
        form = utils.FormSender(form, url=resp.url)
        form.set('data.TaskScreenName', self.problem_id)
        form.set('data.LanguageId', str(language_id))
        form.set('sourceCode', code)
        resp = form.request(session=session)
        _list_alert(resp, print_=True)

        # result
        if '/submissions/me' in resp.url:
            # example: https://practice.contest.atcoder.jp/submissions/me#32174
            # CAUTION: this URL is not a URL of the submission
            log.success('success: result: %s', resp.url)
            return utils.DummySubmission(resp.url, problem=self)
        else:
            raise SubmissionError('it may be a rate limit')
Beispiel #23
0
 def get_available_languages(
         self,
         session: Optional[requests.Session] = None) -> List[Language]:
     session = session or utils.new_default_session()
     info = self._get_model(session=session)
     lang_display_mapping = self._get_lang_display_mapping()
     result = []  # type: List[Language]
     for lang in info['languages']:
         descr = lang_display_mapping.get(lang)
         if descr is None:
             log.warning('display mapping for language `%s\' not found',
                         lang)
             descr = lang
         result += [Language(lang, descr)]
     return result
Beispiel #24
0
    def submit_code(
        self,
        code: bytes,
        language_id: LanguageId,
        filename: Optional[str] = None,
        session: Optional[requests.Session] = None
    ) -> onlinejudge.type.Submission:
        """
        :raises NotLoggedInError:
        :raises SubmissionError:
        """

        session = session or utils.new_default_session()
        if not self.get_service().is_logged_in(session=session):
            raise NotLoggedInError
        # get
        resp = utils.request('GET', self.get_url(), session=session)
        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        csrftoken = soup.find('meta', attrs={
            'name': 'csrf-token'
        }).attrs['content']
        # post
        url = 'https://www.hackerrank.com/rest/contests/{}/challenges/{}/submissions'.format(
            self.contest_slug, self.challenge_slug)
        payload = {
            'code': code,
            'language': str(language_id),
            'contest_slug': self.contest_slug
        }
        log.debug('payload: %s', payload)
        resp = utils.request('POST',
                             url,
                             session=session,
                             json=payload,
                             headers={'X-CSRF-Token': csrftoken})
        # parse
        it = json.loads(resp.content.decode())
        log.debug('json: %s', it)
        if not it['status']:
            log.failure('Submit Code: failed')
            raise SubmissionError
        model_id = it['model']['id']
        url = self.get_url().rstrip('/') + '/submissions/code/{}'.format(
            model_id)
        log.success('success: result: %s', url)
        return utils.DummySubmission(url, problem=self)
Beispiel #25
0
 def download_system_cases(
         self,
         session: Optional[requests.Session] = None) -> List[TestCase]:
     session = session or utils.new_default_session()
     # example: https://www.hackerrank.com/rest/contests/hourrank-1/challenges/beautiful-array/download_testcases
     url = 'https://www.hackerrank.com/rest/contests/{}/challenges/{}/download_testcases'.format(
         self.contest_slug, self.challenge_slug)
     resp = utils.request('GET',
                          url,
                          session=session,
                          raise_for_status=False)
     if resp.status_code != 200:
         log.error('response: %s', resp.content.decode())
         return []
     return onlinejudge._implementation.testcase_zipper.extract_from_zip(
         resp.content, '%eput/%eput%s.txt')
    def list_problems(
            self,
            session: Optional[requests.Session] = None
    ) -> List['AtCoderProblem']:
        # get
        session = session or utils.new_default_session()
        url = 'https://atcoder.jp/contests/{}/tasks'.format(self.contest_id)
        resp = _request('GET', url, session=session)

        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        tbody = soup.find('tbody')
        return [
            AtCoderProblem._from_table_row(tr) for tr in tbody.find_all('tr')
        ]
    def download_system_cases(
            self,
            session: Optional[requests.Session] = None) -> List[TestCase]:
        """
        :raises NotLoggedInError:
        """

        session = session or utils.new_default_session()
        if not self.get_service().is_logged_in(session=session):
            raise NotLoggedInError
        url = 'https://yukicoder.me/problems/no/{}/testcase.zip'.format(
            self.problem_no)
        resp = utils.request('GET', url, session=session)
        fmt = 'test_%e/%s'
        return onlinejudge._implementation.testcase_zipper.extract_from_zip(
            resp.content, fmt)
Beispiel #28
0
    def submit_code(
        self,
        code: bytes,
        language_id: LanguageId,
        filename: Optional[str] = None,
        session: Optional[requests.Session] = None
    ) -> onlinejudge.type.Submission:
        """
        :raises NotLoggedInError:
        :raises SubmissionError:
        """

        session = session or utils.new_default_session()
        # get
        resp = utils.request('GET', self.get_url(), session=session)
        # parse
        soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                 utils.html_parser)
        form = soup.find('form', class_='submitForm')
        if form is None:
            log.error('not logged in')
            raise NotLoggedInError
        log.debug('form: %s', str(form))
        # make data
        form = utils.FormSender(form, url=resp.url)
        form.set('programTypeId', language_id)
        form.set_file('sourceFile', filename or 'code', code)
        resp = form.request(session=session)
        resp.raise_for_status()
        # result
        if resp.url.endswith('/my'):
            # example: https://codeforces.com/contest/598/my
            log.success('success: result: %s', resp.url)
            return utils.DummySubmission(resp.url, problem=self)
        else:
            log.failure('failure')
            # parse error messages
            soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                                     utils.html_parser)
            msgs = []  # type: List[str]
            for span in soup.findAll('span', class_='error'):
                msgs += [span.string]
                log.warning('Codeforces says: "%s"', span.string)
            raise SubmissionError(
                'it may be the "You have submitted exactly the same code before" error: '
                + str(msgs))
 def download_sample_cases(
         self,
         session: Optional[requests.Session] = None) -> List[TestCase]:
     session = session or utils.new_default_session()
     # get
     resp = utils.request('GET', self.get_url(), session=session)
     # parse
     soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding),
                              utils.html_parser)
     samples = onlinejudge._implementation.testcase_zipper.SampleZipper()
     for pre in soup.select('.sample pre'):
         log.debug('pre: %s', str(pre))
         it = self._parse_sample_tag(pre)
         if it is not None:
             data, name = it
             samples.add(data.encode(), name)
     return samples.get()
Beispiel #30
0
def login(args: 'argparse.Namespace') -> None:
    # get service
    service = onlinejudge.dispatch.service_from_url(args.url)
    if service is None:
        sys.exit(1)

    # configure
    kwargs = {}
    if service.get_name() == 'yukicoder':
        if not args.method:
            args.method = 'github'
        if args.method not in ['github', 'twitter']:
            log.failure('login for yukicoder: invalid option: --method %s', args.method)
            sys.exit(1)
        kwargs['method'] = args.method
    else:
        if args.method:
            log.failure('login for %s: invalid option: --method %s', service.get_name(), args.method)
            sys.exit(1)

    with utils.with_cookiejar(utils.new_default_session(), path=args.cookie) as sess:

        if args.check:
            if service.is_logged_in(session=sess):
                log.info('You have already signed in.')
            else:
                log.info('You are not signed in.')
                sys.exit(1)

        else:
            # login
            def get_credentials() -> Tuple[str, str]:
                if args.username is None:
                    args.username = input('Username: '******'If you don\'t want to give your password to this program, you can give only your session tokens.')
            log.info('see: https://github.com/kmyk/online-judge-tools/blob/master/LOGIN_WITH_COOKIES.md')

            try:
                service.login(get_credentials, session=sess, **kwargs)  # type: ignore
            except onlinejudge.type.LoginError:
                pass