예제 #1
0
 def login(self, get_credentials, session=None):
     session = session or utils.new_default_session()
     url = 'https://practice.contest.atcoder.jp/login'
     # get
     resp = utils.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:
         return 'login' not in resp.url
     # post
     username, password = get_credentials()
     resp = utils.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)
     return 'login' not in resp.url  # AtCoder redirects to the top page if success
예제 #2
0
 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
예제 #3
0
def generate_output(args: 'argparse.Namespace') -> None:
    if not args.test:
        args.test = cutils.glob_with_format(args.directory, args.format) # by default
    if args.ignore_backup:
        args.test = cutils.drop_backup_or_hidden_files(args.test)
    tests = cutils.construct_relationship_of_files(args.test, args.directory, args.format)
    for name, it in sorted(tests.items()):
        log.emit('')
        log.info('%s', name)
        if 'out' in it:
            log.info('output file already exists.')
            log.info('skipped.')
            continue
        with it['in'].open() as inf:
            begin = time.perf_counter()
            answer, proc = utils.exec_command(args.command, shell=True, stdin=inf)
            end = time.perf_counter()
            log.status('time: %f sec', end - begin)
        if proc.returncode != 0:
            log.failure(log.red('RE') + ': return code %d', proc.returncode)
            log.info('skipped.')
            continue
        log.emit(log.bold(answer.decode().rstrip()))
        match_result = cutils.match_with_format(args.directory, args.format, it['in'])  # type: Optional[Match[Any]]
        if match_result is not None:
            matched_name = match_result.groupdict()['name']  # type: str
        else:
            assert False
        path = cutils.path_from_format(args.directory, args.format, name=matched_name, ext='out')
        if not path.parent.is_dir():
            os.makedirs(str(path.parent), exist_ok=True)
        with path.open('wb') as fh:
            fh.write(answer)
        log.success('saved to: %s', path)
예제 #4
0
 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
예제 #5
0
 def login(self, get_credentials, session=None):
     session = session or utils.new_default_session()
     url = "https://practice.contest.atcoder.jp/login"
     # get
     resp = utils.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:
         return "login" not in resp.url
     # post
     username, password = get_credentials()
     resp = utils.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)
     return "login" not in resp.url  # AtCoder redirects to the top page if success
예제 #6
0
 def download_with_running_code(
         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)
     csrftoken = soup.find('meta', attrs={
         'name': 'csrf-token'
     }).attrs['content']
     # post
     url = 'https://www.hackerrank.com/rest/contests/{}/challenges/{}/compile_tests'.format(
         self.contest_slug, self.challenge_slug)
     payload = {'code': ':', 'language': 'bash', 'customtestcase': False}
     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.error('Run Code: failed')
         return []
     model_id = it['model']['id']
     now = datetime.datetime.now()
     unixtime = int(datetime.datetime.now().timestamp() * 10**3)
     url = 'https://www.hackerrank.com/rest/contests/{}/challenges/{}/compile_tests/{}?_={}'.format(
         self.contest_slug, self.challenge_slug, it['model']['id'],
         unixtime)
     # sleep
     log.status('sleep(3)')
     time.sleep(3)
     # get
     resp = utils.request('GET',
                          url,
                          session=session,
                          headers={'X-CSRF-Token': csrftoken})
     # parse
     it = json.loads(resp.content.decode())
     log.debug('json: %s', it)
     if not it['status']:
         log.error('Run Code: failed')
         return []
     samples: List[TestCase] = []
     for i, (inf, outf) in enumerate(
             zip(it['model']['stdin'], it['model']['expected_output'])):
         inname = 'Testcase {} Input'.format(i)
         outname = 'Testcase {} Expected Output'.format(i)
         samples += [
             TestCase(
                 LabeledString(inname, utils.textfile(inf)),
                 LabeledString(outname, utils.textfile(outf)),
             )
         ]
     return samples
예제 #7
0
 def login(self,
           get_credentials: onlinejudge.type.CredentialsProvider,
           session: Optional[requests.Session] = None) -> bool:
     session = session or utils.new_default_session()
     # 自分で書き換えた箇所
     # url = 'https://practice.contest.atcoder.jp/login'
     url = 'https://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:
         return 'login' not in resp.url
     # post
     username, password = get_credentials()
     # 自分で書き換えた箇所(CSRF対策)
     soup = bs4.BeautifulSoup(resp.text, 'lxml')
     csrftoken = soup.find_all('input')[0]['value']
     resp = _request('POST',
                     url,
                     session=session,
                     data={
                         'csrf_token': csrftoken,
                         'username': username,
                         'password': password
                     },
                     allow_redirects=False)
     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
예제 #8
0
 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()
예제 #9
0
def generate_output(args):
    if not args.test:
        args.test = glob_with_format(args.format) # by default
    if args.ignore_backup:
        args.test = drop_backup_or_hidden_files(args.test)
    tests = construct_relationship_of_files(args.test, args.format)
    for name, it in sorted(tests.items()):
        log.emit('')
        log.info('%s', name)
        if 'out' in it:
            log.info('output file already exists.')
            log.info('skipped.')
            continue
        with open(it['in']) as inf:
            begin = time.perf_counter()
            answer, proc = utils.exec_command(args.command, shell=args.shell, stdin=inf)
            end = time.perf_counter()
            log.status('time: %f sec', end - begin)
        if proc.returncode != 0:
            log.failure(log.red('RE') + ': return code %d', proc.returncode)
            log.info('skipped.')
            continue
        log.emit(log.bold(answer.decode().rstrip()))
        path = path_from_format(args.format, match_with_format(args.format, it['in']).groupdict()['name'], 'out')
        with open(path, 'w') as fh:
            fh.buffer.write(answer)
        log.success('saved to: %s', path)
예제 #10
0
 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()
예제 #11
0
    def login(self, get_credentials, session=None):
        driver = session  # rename
        assert isinstance(driver,
                          selenium.webdriver.remote.webdriver.WebDriver)

        # go to the login page
        url = 'https://accounts.topcoder.com/member'
        driver.get(url)
        log.status('wait for redirect...')
        time.sleep(3)
        if driver.current_url != url:
            log.info('You have already logged in.')
            return True

        # type credentials and click login
        username, password = get_credentials()
        driver.find_element_by_xpath(
            '//form[@name="vm.loginForm"]//input[@name="username"]').send_keys(
                username)
        driver.find_element_by_xpath(
            '//form[@name="vm.loginForm"]//input[@id="current-password-input"]'
        ).send_keys(password)
        driver.find_element_by_xpath(
            '//form[@name="vm.loginForm"]//button[@type="submit" and text()="Log In"]'
        ).click()

        # wait a minute
        log.info('Logging in...')
        time.sleep(6)
        if driver.current_url != url:
            log.success('Success')
            return True
        else:
            log.failure('Failure')
            return False
예제 #12
0
 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
예제 #13
0
 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()
예제 #14
0
def submission_from_url(s):
    for cls in submissions:
        it = cls.from_url(s)
        if it is not None:
            log.status('submission recognized: %s: %s', str(it), s)
            return it
    log.failure('unknown submission: %s', s)
예제 #15
0
def submission_from_url(s: str) -> Optional['Submission']:
    for cls in submissions:
        submission = cls.from_url(s)
        if submission is not None:
            log.status('submission recognized: %s: %s', str(submission), s)
            return submission
    log.failure('unknown submission: %s', s)
    return None
예제 #16
0
def format_code(code: bytes, dos2unix: bool = False, rstrip: bool = False) -> bytes:
    if dos2unix:
        log.status('dos2unix...')
        code = code.replace(b'\r\n', b'\n')
    if rstrip:
        log.status('rstrip...')
        code = code.rstrip()
    return code
 def call_generate_scanner(self, url, expected, options=[]):
     cmd = [self.ojtools, '-v', 'generate-scanner', url] + options
     output = subprocess.check_output(cmd, stderr=sys.stderr).decode()
     log.status('result:\n%s', output)
     if expected != output:
         log.error('expected:\n%s' % expected)
     self.assertEqual(expected, output)
     time.sleep(1)
예제 #18
0
 def _report_messages(cls,
                      msgs: List[str],
                      unexpected: bool = False) -> bool:
     for msg in msgs:
         log.status('message: %s', msg)
     if msgs and unexpected:
         log.failure('unexpected messages found')
     return bool(msgs)
예제 #19
0
 def _flush(self) -> None:
     # halve the size if it is more than 1MiB
     if self.path.stat().st_size >= 1024 * 1024:
         with open(str(self.path)) as fh:
             history_lines = fh.readlines()
         with open(str(self.path), 'w') as fh:
             fh.write(''.join(history_lines[:-len(history_lines) // 2]))
         log.status('halve history at: %s', self.path)
예제 #20
0
def request(method, url, session=None, raise_for_status=True, **kwargs):
    assert method in ['GET', 'POST']
    kwargs.setdefault('allow_redirects', True)
    log.status('%s: %s', method, url)
    resp = session.request(method, url, **kwargs)
    log.status(describe_status_code(resp.status_code))
    if raise_for_status:
        resp.raise_for_status()
    return resp
예제 #21
0
def download(args):
    # prepare values
    problem = onlinejudge.dispatch.problem_from_url(args.url)
    if problem is None:
        sys.exit(1)
    kwargs = {}
    if args.system:
        supported_service_names = ["aoj", "yukicoder"]
        if problem.get_service().get_name() not in supported_service_names:
            log.error("--system for %s is not supported",
                      problem.get_service().get_name())
            sys.exit(1)
        kwargs["is_system"] = True
    if args.format is None:
        if kwargs.get("is_system"):
            if problem.get_service().get_name() == "yukicoder":
                args.format = "%b.%e"
            else:
                args.format = "%i.%e"
        else:
            args.format = "sample-%i.%e"

    # get samples from the server
    with utils.with_cookiejar(utils.new_default_session(),
                              path=args.cookie) as sess:
        samples = problem.download(session=sess, **kwargs)

    # write samples to files
    for i, sample in enumerate(samples):
        log.emit("")
        log.info("sample %d", i)
        for kind in ["input", "output"]:
            ext = kind[:-3]
            data = sample[kind]["data"]
            name = sample[kind]["name"]
            table = {}
            table["i"] = str(i + 1)
            table["e"] = ext
            table["n"] = name
            table["b"] = os.path.basename(name)
            table["d"] = os.path.dirname(name)
            path = os.path.join(args.directory,
                                utils.parcentformat(args.format, table))
            log.status("%sput: %s", ext, name)
            log.emit(colorama.Style.BRIGHT + data.rstrip() +
                     colorama.Style.RESET_ALL)
            if args.dry_run:
                continue
            if os.path.exists(path):
                log.warning("file already exists: %s", path)
                if not args.overwrite:
                    log.warning("skipped")
                    continue
            os.makedirs(os.path.dirname(path), exist_ok=True)
            with open(path, "w", encoding="utf-8") as fh:
                fh.write(data)
            log.success("saved to: %s", path)
예제 #22
0
def download(args: 'argparse.Namespace') -> None:
    # prepare values
    problem = onlinejudge.dispatch.problem_from_url(args.url)
    if problem is None:
        sys.exit(1)
    kwargs = {}
    if args.system:
        supported_service_names = ['aoj', 'yukicoder']
        if problem.get_service().get_name() not in supported_service_names:
            log.error('--system for %s is not supported',
                      problem.get_service().get_name())
            sys.exit(1)
        kwargs['is_system'] = True
    if args.format is None:
        if kwargs.get('is_system'):
            if problem.get_service().get_name() == 'yukicoder':
                args.format = '%b.%e'
            else:
                args.format = '%i.%e'
        else:
            args.format = 'sample-%i.%e'

    # get samples from the server
    with utils.with_cookiejar(utils.new_default_session(),
                              path=args.cookie) as sess:
        samples = problem.download(session=sess, **kwargs)  # type: ignore

    # write samples to files
    for i, sample in enumerate(samples):
        log.emit('')
        log.info('sample %d', i)
        for kind in ['input', 'output']:
            ext = kind[:-3]
            data = getattr(sample, kind).data
            name = getattr(sample, kind).name
            table = {}
            table['i'] = str(i + 1)
            table['e'] = ext
            table['n'] = name
            table['b'] = os.path.basename(name)
            table['d'] = os.path.dirname(name)
            path = os.path.join(args.directory,
                                utils.parcentformat(args.format, table))
            log.status('%sput: %s', ext, name)
            log.emit(colorama.Style.BRIGHT + data.rstrip() +
                     colorama.Style.RESET_ALL)
            if args.dry_run:
                continue
            if os.path.exists(path):
                log.warning('file already exists: %s', path)
                if not args.overwrite:
                    log.warning('skipped')
                    continue
            os.makedirs(os.path.dirname(path), exist_ok=True)
            with open(path, 'w') as fh:
                fh.write(data)
            log.success('saved to: %s', path)
예제 #23
0
def request(method, url, session=None, raise_for_status=True, **kwargs):
    assert method in ["GET", "POST"]
    kwargs.setdefault("allow_redirects", True)
    log.status("%s: %s", method, url)
    resp = session.request(method, url, **kwargs)
    log.status(describe_status_code(resp.status_code))
    if raise_for_status:
        resp.raise_for_status()
    return resp
예제 #24
0
def problem_from_url(s):
    for cls in problems:
        it = cls.from_url(s)
        if it is not None:
            log.status('problem recognized: %s: %s', str(it), s)
            return it
    it = submission_from_url(s)
    if it is not None:
        return it.get_problem()
    log.failure('unknown problem: %s', s)
예제 #25
0
def problem_from_url(s: str) -> Optional['Problem']:
    for cls in problems:
        problem = cls.from_url(s)
        if problem is not None:
            log.status('problem recognized: %s: %s', str(problem), s)
            return problem
    submission = submission_from_url(s)
    if submission is not None:
        return submission.get_problem()
    log.failure('unknown problem: %s', s)
    return None
예제 #26
0
def submit(args):
    problem = onlinejudge.dispatch.problem_from_url(args.url)
    if problem is None:
        sys.exit(1)
    # code
    with open(args.file) as fh:
        code = fh.buffer.read()
    try:
        s = code.decode()  # for logging
    except UnicodeDecodeError as e:
        log.failure('%s: %s', e.__class__.__name__, str(e))
        s = repr(code)[1:]
    log.info('code:')
    log.emit(log.bold(s))
    # session
    with utils.session(cookiejar=args.cookie) as sess:
        # language
        langs = problem.get_language_dict(session=sess)
        if args.language not in langs:
            log.error('language is unknown')
            log.info('supported languages are:')
            for lang in sorted(langs.keys()):
                log.emit('%s (%s)', lang, langs[lang]['description'])
            sys.exit(1)
        # confirm
        if args.wait:
            log.status('sleep(%.2f)', args.wait)
            time.sleep(args.wait)
        if not args.yes:
            sys.stdout.write('Are you sure? [y/N] ')
            sys.stdout.flush()
            c = sys.stdin.read(1)
            if c != 'y':
                log.info('terminated.')
                return
        # submit
        url = problem.submit(code, language=args.language, session=sess)
        if url and args.open:
            if not isinstance(args.open, str):
                args.open = None
                for browser in default_url_opener:
                    args.open = shutil.which(browser)
                    if args.open:
                        break
            if not args.open:
                log.failure('couldn\'t open the url. please specify a browser')
            else:
                log.info('open the submission page with: %s', args.open)
                subprocess.check_call([args.open, url],
                                      stdin=sys.stdin,
                                      stdout=sys.stdout,
                                      stderr=sys.stderr)
예제 #27
0
def service_from_url(s):
    for cls in services:
        it = cls.from_url(s)
        if it is not None:
            log.status('service recognized: %s: %s', str(it), s)
            return it
    it = submission_from_url(s)
    if it is not None:
        return it.get_service()
    it = problem_from_url(s)
    if it is not None:
        return it.get_service()
    log.failure('unknown service: %s', s)
예제 #28
0
 def request(self, session, action=None, **kwargs):
     action = action or self.form['action']
     url = urllib.parse.urljoin(self.url, action)
     method = self.form['method'].upper()
     log.status('%s: %s', method, url)
     log.debug('payload: %s', str(self.payload))
     resp = session.request(method,
                            url,
                            data=self.payload,
                            files=self.files,
                            **kwargs)
     log.status(describe_status_code(resp.status_code))
     return resp
예제 #29
0
def with_cookiejar(
    session: requests.Session,
    path: pathlib.Path = default_cookie_path
) -> Generator[requests.Session, None, None]:
    session.cookies = http.cookiejar.LWPCookieJar(str(path))  # type: ignore
    if path.exists():
        log.status('load cookie from: %s', path)
        session.cookies.load()  # type: ignore
    yield session
    log.status('save cookie to: %s', path)
    path.parent.mkdir(parents=True, exist_ok=True)
    session.cookies.save()  # type: ignore
    path.chmod(0o600)  # NOTE: to make secure a little bit
예제 #30
0
def request(method: str,
            url: str,
            session: requests.Session,
            raise_for_status: bool = True,
            **kwargs) -> requests.Response:
    assert method in ['GET', 'POST']
    kwargs.setdefault('allow_redirects', True)
    log.status('%s: %s', method, url)
    resp = session.request(method, url, **kwargs)
    log.status(describe_status_code(resp.status_code))
    if raise_for_status:
        resp.raise_for_status()
    return resp