From 4c812c43e2daffec8bbba4389b711699066f321c Mon Sep 17 00:00:00 2001 From: Vadzim Verhasau Date: Thu, 18 Mar 2021 00:52:47 +0300 Subject: [PATCH] Small fixes (#7) * Renamed variables to not conflict with Python reserved words. * Removed wildcard import. * Added Tests passing in README. * Code refactor. --- .github/workflows/codestyle.yml | 2 + .github/workflows/test.yml | 2 + README.md | 3 +- codeforces_api/api_request_maker.py | 20 ++-- codeforces_api/api_requests.py | 19 ++- codeforces_api/types.py | 47 ++++---- codeforces_api/version.py | 2 +- tests/test_api.py | 174 ++++++++++++++-------------- 8 files changed, 140 insertions(+), 129 deletions(-) diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 9aaf516..2bca66f 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -4,9 +4,11 @@ on: push: branches: - master + - develop pull_request: branches: - master + - develop jobs: build: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca208bc..acd757b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,9 +4,11 @@ on: push: branches: - master + - develop pull_request: branches: - master + - develop jobs: build: diff --git a/README.md b/README.md index 9462923..489bdbb 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@ Codeforces API [![Stars](https://img.shields.io/github/stars/VadVergasov/CodeforcesApiPy)](https://github.com/VadVergasov/CodeforcesApiPy/stargazers) [![Forks](https://img.shields.io/github/forks/VadVergasov/CodeforcesApiPy)](https://github.com/VadVergasov/CodeforcesApiPy/network/members) [![Issues](https://img.shields.io/github/issues/VadVergasov/CodeforcesApiPy)](https://github.com/VadVergasov/CodeforcesApiPy/issues) -[![Publish to PyPI and TestPyPI](https://github.com/VadVergasov/CodeforcesApiPy/workflows/Publish%20to%20PyPI%20and%20TestPyPI/badge.svg?branch=master)](https://pypi.org/project/CodeforcesApiPy/) +[![Publish to PyPI and creating Release](https://github.com/VadVergasov/CodeforcesApiPy/workflows/Publish%20to%20PyPI%20and%20TestPyPI/badge.svg?branch=master)](https://pypi.org/project/CodeforcesApiPy/) [![Generate wiki](https://github.com/VadVergasov/CodeforcesApiPy/workflows/Generate%20wiki/badge.svg?branch=master)](https://github.com/VadVergasov/CodeforcesApiPy/wiki) +[![Testing](https://github.com/VadVergasov/CodeforcesApiPy/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/VadVergasov/CodeforcesApiPy/actions/workflows/test.yml) [![Downloads](https://static.pepy.tech/personalized-badge/codeforcesapipy?period=total&units=international_system&left_color=black&right_color=blue&left_text=Total%20downloads)](https://pepy.tech/project/codeforcesapipy) ![Codestyle](https://img.shields.io/badge/code%20style-black-000000.svg) ========== diff --git a/codeforces_api/api_request_maker.py b/codeforces_api/api_request_maker.py index aa188f2..bbb0f31 100644 --- a/codeforces_api/api_request_maker.py +++ b/codeforces_api/api_request_maker.py @@ -23,9 +23,9 @@ class CodeforcesApiRequestMaker: - api_key = "" - secret = "" - rand = 0 + _api_key = "" + _secret = "" + _rand = 0 assigned_rand = False anonimus = False @@ -46,10 +46,10 @@ def __init__(self, api_key=None, secret=None, random_number=1000000): if api_key is None and secret is None: self.anonimus = True else: - self.api_key = api_key - self.secret = secret + self._api_key = api_key + self._secret = secret self.anonimus = False - self.rand = random_number + self._rand = random_number def generate_request(self, method_name, **fields): """ @@ -65,9 +65,9 @@ def generate_request(self, method_name, **fields): self.renew_rand() current_time = time.time() - fields["apiKey"] = str(self.api_key) + fields["apiKey"] = str(self._api_key) fields["time"] = str(int(current_time)) - api_signature = str(self.rand) + "/" + method_name + "?" + api_signature = str(self._rand) + "/" + method_name + "?" fields = collections.OrderedDict(sorted(fields.items())) for i in fields: api_signature += str(i) + "=" @@ -78,9 +78,9 @@ def generate_request(self, method_name, **fields): api_signature += str(fields[i]) api_signature += "&" api_signature = api_signature[:-1] - api_signature += "#" + str(self.secret) + api_signature += "#" + str(self._secret) hashed_signature = hashlib.sha512(api_signature.encode("utf-8")) - fields["apiSig"] = str(self.rand) + str(hashed_signature.hexdigest()) + fields["apiSig"] = str(self._rand) + str(hashed_signature.hexdigest()) return {"request_url": request_url, "data": fields} def check_return_code(self, response): diff --git a/codeforces_api/api_requests.py b/codeforces_api/api_requests.py index ba476e7..a31906c 100644 --- a/codeforces_api/api_requests.py +++ b/codeforces_api/api_requests.py @@ -17,7 +17,19 @@ import requests from codeforces_api.api_request_maker import CodeforcesApiRequestMaker -from codeforces_api.types import * +from codeforces_api.types import ( + User, + BlogEntry, + Comment, + RecentAction, + RatingChange, + Contest, + Problem, + ProblemStatistic, + Submission, + Hack, + RanklistRow, +) class CodeforcesApi(CodeforcesApiRequestMaker): @@ -155,9 +167,6 @@ def contest_standings( handles_str = "" for handle in handles: handles_str += str(handle) + ";" - request_data = self.generate_request( - "user.info", **{"handles": handles_str} - ) parameters["handles"] = handles_str if room != -1: parameters["room"] = str(room) @@ -185,7 +194,7 @@ def contest_status(self, contest_id, handle="", start=-1, count=-1): Returns parsed response from codeforces.com. """ - if contest_id == None: + if contest_id is None: raise TypeError("Contest_id is required") parameters = {"contestId": str(contest_id)} if handle != "": diff --git a/codeforces_api/types.py b/codeforces_api/types.py index de2ddeb..c77f3a1 100644 --- a/codeforces_api/types.py +++ b/codeforces_api/types.py @@ -13,8 +13,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -""" -""" Source of inspiration: https://github.com/eternnoir/pyTelegramBotAPI/blob/master/telebot/types.py """ import json @@ -60,10 +58,9 @@ def check_json(json_type): """ if isinstance(json_type, dict): return json_type - elif isinstance(json_type, str): + if isinstance(json_type, str): return json.loads(json_type) - else: - raise ValueError("json_type should be a json dict or string.") + raise ValueError("json_type should be a json dict or string.") def __str__(self): d = {} @@ -194,7 +191,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - id = obj["id"] + identifier = obj["id"] original_locale = obj["originalLocale"] creation_time_seconds = obj["creationTimeSeconds"] author_handle = obj["authorHandle"] @@ -206,7 +203,7 @@ def de_json(cls, json_string): rating = obj["rating"] content = obj.get("content") return cls( - id, + identifier, original_locale, creation_time_seconds, author_handle, @@ -221,7 +218,7 @@ def de_json(cls, json_string): def __init__( self, - id, + identifier, original_locale, creation_time_seconds, author_handle, @@ -233,7 +230,7 @@ def __init__( rating, content=None, ): - self.id = id + self.id = identifier self.original_locale = original_locale self.creation_time_seconds = creation_time_seconds self.author_handle = author_handle @@ -267,7 +264,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - id = obj["id"] + identifier = obj["id"] creation_time_seconds = obj["creationTimeSeconds"] commentator_handle = obj["commentatorHandle"] locale = obj["locale"] @@ -275,7 +272,7 @@ def de_json(cls, json_string): rating = obj["rating"] parent_comment_id = obj.get("parentCommentId") return cls( - id, + identifier, creation_time_seconds, commentator_handle, locale, @@ -286,7 +283,7 @@ def de_json(cls, json_string): def __init__( self, - id, + identifier, creation_time_seconds, commentator_handle, locale, @@ -294,7 +291,7 @@ def __init__( rating, parent_comment_id=None, ): - self.id = id + self.id = identifier self.creation_time_seconds = creation_time_seconds self.commentator_handle = commentator_handle self.locale = locale @@ -401,7 +398,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - id = obj["id"] + identifier = obj["id"] name = obj["name"] contest_type = obj["type"] phase = obj["phase"] @@ -419,7 +416,7 @@ def de_json(cls, json_string): city = obj.get("city") season = obj.get("season") return cls( - id, + identifier, name, contest_type, phase, @@ -440,7 +437,7 @@ def de_json(cls, json_string): def __init__( self, - id, + identifier, name, contest_type, phase, @@ -458,7 +455,7 @@ def __init__( city=None, season=None, ): - self.id = id + self.id = identifier self.name = name self.contest_type = contest_type self.phase = phase @@ -650,7 +647,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - id = obj["id"] + identifier = obj["id"] creation_time_seconds = obj["creationTimeSeconds"] relative_time_seconds = obj["relativeTimeSeconds"] problem = Problem.de_json(obj["problem"]) @@ -664,7 +661,7 @@ def de_json(cls, json_string): verdict = obj.get("verdict") points = obj.get("points") return cls( - id, + identifier, creation_time_seconds, relative_time_seconds, problem, @@ -681,7 +678,7 @@ def de_json(cls, json_string): def __init__( self, - id, + identifier, creation_time_seconds, relative_time_seconds, problem, @@ -695,7 +692,7 @@ def __init__( verdict=None, points=None, ): - self.id = id + self.id = identifier self.creation_time_seconds = creation_time_seconds self.relative_time_seconds = relative_time_seconds self.problem = problem @@ -733,7 +730,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - id = obj["id"] + identifier = obj["id"] creation_time_seconds = obj["creationTimeSeconds"] hacker = Party.de_json(obj["hacker"]) defender = Party.de_json(obj["defender"]) @@ -742,7 +739,7 @@ def de_json(cls, json_string): test = obj.get("test") judge_protocol = obj.get("judgeProtocol") return cls( - id, + identifier, creation_time_seconds, hacker, defender, @@ -754,7 +751,7 @@ def de_json(cls, json_string): def __init__( self, - id, + identifier, creation_time_seconds, hacker, defender, @@ -763,7 +760,7 @@ def __init__( test=None, judge_protocol=None, ): - self.id = id + self.id = identifier self.creation_time_seconds = creation_time_seconds self.hacker = hacker self.defender = defender diff --git a/codeforces_api/version.py b/codeforces_api/version.py index 34c5111..ff6ef86 100644 --- a/codeforces_api/version.py +++ b/codeforces_api/version.py @@ -1 +1 @@ -__version__ = "2.0.5" +__version__ = "2.0.6" diff --git a/tests/test_api.py b/tests/test_api.py index 82bde26..9f015eb 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -20,7 +20,7 @@ def test_blog_entry_view(api_key, api_secret): assert blog_entry.original_locale == "ru" assert blog_entry.id == 74291 assert blog_entry.title == "

Codeforces API python

" - assert blog_entry.allow_view_history == True + assert blog_entry.allow_view_history assert blog_entry.tags == [ "#api", "api", @@ -45,7 +45,7 @@ def test_contest_hacks(api_key, api_secret): "verdict": "Invalid input", } assert hack.hacker.participant_type == "PRACTICE" - assert hack.hacker.ghost == False + assert not hack.hacker.ghost assert hack.hacker.members[0].handle == "VietCT" assert hack.hacker.team_id is None assert hack.hacker.contest_id == 1311 @@ -53,7 +53,7 @@ def test_contest_hacks(api_key, api_secret): assert hack.hacker.start_time_seconds == 1582554900 assert hack.defender.members[0].handle == "UMR" assert hack.defender.participant_type == "OUT_OF_COMPETITION" - assert hack.defender.ghost == False + assert not hack.defender.ghost assert hack.defender.team_id is None assert hack.defender.contest_id == 1311 assert hack.defender.room is None @@ -72,13 +72,13 @@ def test_contest_hacks(api_key, api_secret): def test_contest_list(): api = CodeforcesApi() - list = api.contest_list() - for contest in list: + contests = api.contest_list() + for contest in contests: if contest.id == 1496: assert contest.name == "Codeforces Round #706 (Div. 2)" assert contest.contest_type == "CF" assert contest.phase == "FINISHED" - assert contest.frozen == False + assert not contest.frozen assert contest.duration_seconds == 7200 assert contest.start_time_seconds == 1615377900 assert contest.prepared_by is None @@ -114,7 +114,7 @@ def test_contest_standings(api_key, api_secret): assert standings["contest"].name == "Codeforces Round #622 (Div. 2)" assert standings["contest"].contest_type == "CF" assert standings["contest"].phase == "FINISHED" - assert standings["contest"].frozen == False + assert not standings["contest"].frozen assert standings["contest"].duration_seconds == 7200 assert standings["contest"].start_time_seconds == 1582448700 assert standings["contest"].prepared_by is None @@ -140,7 +140,7 @@ def test_contest_standings(api_key, api_secret): if row.party.members[0].handle == "VadVergasov": assert row.rank == 2303 assert row.party.participant_type == "CONTESTANT" - assert row.party.ghost == False + assert not row.party.ghost assert row.party.team_id is None assert row.party.contest_id == 1313 assert row.party.room == 10 @@ -182,7 +182,7 @@ def test_contest_status(): assert row.problem.tags == ["brute force", "greedy", "implementation"] assert row.author.members[0].handle == "VadVergasov" assert row.author.participant_type == "CONTESTANT" - assert row.author.ghost == False + assert not row.author.ghost assert row.author.team_id is None assert row.author.contest_id == 1313 assert row.author.room == 10 @@ -210,37 +210,37 @@ def test_problemset_problems(api_key, api_secret): assert problem.rating == 1000 assert problem.tags == ["implementation"] for statistic in problemset["problem_statistics"]: - assert type(statistic.index) is str - assert type(statistic.solved_count) is int - assert type(statistic.contest_id) is int + assert isinstance(statistic.index, str) + assert isinstance(statistic.solved_count, int) + assert isinstance(statistic.contest_id, int) def test_recent_status(api_key, api_secret): api = CodeforcesApi(api_key, api_secret) status = api.problemset_recent_status(1)[0] - assert type(status.id) is int - assert type(status.creation_time_seconds) is int - assert type(status.relative_time_seconds) is int - assert type(status.problem) is Problem - assert type(status.author) is Party - assert type(status.programming_language) is str - assert type(status.testset) is str - assert type(status.passed_test_count) is int - assert type(status.time_consumed_millis) is int - assert type(status.memory_consumed_bytes) is int - assert type(status.contest_id) is int - assert status.verdict is None or type(status.verdict) is str - assert status.points is None or type(status.points) is float + assert isinstance(status.id, int) + assert isinstance(status.creation_time_seconds, int) + assert isinstance(status.relative_time_seconds, int) + assert isinstance(status.problem, Problem) + assert isinstance(status.author, Party) + assert isinstance(status.programming_language, str) + assert isinstance(status.testset, str) + assert isinstance(status.passed_test_count, int) + assert isinstance(status.time_consumed_millis, int) + assert isinstance(status.memory_consumed_bytes, int) + assert isinstance(status.contest_id, int) + assert status.verdict is None or isinstance(status.verdict, str) + assert status.points is None or isinstance(status.points, float) def test_recent_actions(api_key, api_secret): api = CodeforcesApi(api_key, api_secret) action = api.recent_actions()[0] - assert type(action.time_seconds) is int + assert isinstance(action.time_seconds, int) if hasattr(action, "blog_entry"): - assert type(action.blog_entry) is BlogEntry + assert isinstance(action.blog_entry, BlogEntry) if hasattr(action, "comment"): - assert type(action.comment) is Comment + assert isinstance(action.comment, Comment) def test_user_blog_entries(api_key, api_secret): @@ -252,7 +252,7 @@ def test_user_blog_entries(api_key, api_secret): assert entry.original_locale == "ru" assert entry.id == 74291 assert entry.title == "

Codeforces API python

" - assert entry.allow_view_history == True + assert entry.allow_view_history assert entry.tags == [ "#api", "api", @@ -274,79 +274,79 @@ def test_user_info(api_key, api_secret): api = CodeforcesApi(api_key, api_secret) info = api.user_info(["VadVergasov", "tourist"]) for user in info: - assert user.email is None or type(user.email) is str - assert user.open_id is None or type(user.open_id) is str - assert user.first_name is None or type(user.first_name) is str - assert user.last_name is None or type(user.last_name) is str - assert user.country is None or type(user.country) is str - assert user.vk_id is None or type(user.vk_id) is str - assert user.country is None or type(user.country) is str - assert user.city is None or type(user.city) is str - assert user.organization is None or type(user.organization) is str - assert type(user.contribution) is int - assert user.rank is None or type(user.rank) is str - assert user.rating is None or type(user.rating) is int - assert user.max_rank is None or type(user.max_rank) is str - assert user.max_rating is None or type(user.max_rating) is int - assert type(user.last_online) is int - assert type(user.registration_time_seconds) is int - assert type(user.friend_of_count) is int - assert type(user.avatar) is str - assert type(user.title_photo) is str + assert user.email is None or isinstance(user.email, str) + assert user.open_id is None or isinstance(user.open_id, str) + assert user.first_name is None or isinstance(user.first_name, str) + assert user.last_name is None or isinstance(user.last_name, str) + assert user.country is None or isinstance(user.country, str) + assert user.vk_id is None or isinstance(user.vk_id, str) + assert user.country is None or isinstance(user.country, str) + assert user.city is None or isinstance(user.city, str) + assert user.organization is None or isinstance(user.organization, str) + assert isinstance(user.contribution, int) + assert user.rank is None or isinstance(user.rank, str) + assert user.rating is None or isinstance(user.rating, int) + assert user.max_rank is None or isinstance(user.max_rank, str) + assert user.max_rating is None or isinstance(user.max_rating, int) + assert isinstance(user.last_online, int) + assert isinstance(user.registration_time_seconds, int) + assert isinstance(user.friend_of_count, int) + assert isinstance(user.avatar, str) + assert isinstance(user.title_photo, str) def test_user_rated_list(): api = CodeforcesApi() users = api.user_rated_list(True) for user in users: - assert user.email is None or type(user.email) is str - assert user.open_id is None or type(user.open_id) is str - assert user.first_name is None or type(user.first_name) is str - assert user.last_name is None or type(user.last_name) is str - assert user.country is None or type(user.country) is str - assert user.vk_id is None or type(user.vk_id) is str - assert user.country is None or type(user.country) is str - assert user.city is None or type(user.city) is str - assert user.organization is None or type(user.organization) is str - assert type(user.contribution) is int - assert user.rank is None or type(user.rank) is str - assert user.rating is None or type(user.rating) is int - assert user.max_rank is None or type(user.max_rank) is str - assert user.max_rating is None or type(user.max_rating) is int - assert type(user.last_online) is int - assert type(user.registration_time_seconds) is int - assert type(user.friend_of_count) is int - assert type(user.avatar) is str - assert type(user.title_photo) is str + assert user.email is None or isinstance(user.email, str) + assert user.open_id is None or isinstance(user.open_id, str) + assert user.first_name is None or isinstance(user.first_name, str) + assert user.last_name is None or isinstance(user.last_name, str) + assert user.country is None or isinstance(user.country, str) + assert user.vk_id is None or isinstance(user.vk_id, str) + assert user.country is None or isinstance(user.country, str) + assert user.city is None or isinstance(user.city, str) + assert user.organization is None or isinstance(user.organization, str) + assert isinstance(user.contribution, int) + assert user.rank is None or isinstance(user.rank, str) + assert user.rating is None or isinstance(user.rating, int) + assert user.max_rank is None or isinstance(user.max_rank, str) + assert user.max_rating is None or isinstance(user.max_rating, int) + assert isinstance(user.last_online, int) + assert isinstance(user.registration_time_seconds, int) + assert isinstance(user.friend_of_count, int) + assert isinstance(user.avatar, str) + assert isinstance(user.title_photo, str) def test_user_rating(): api = CodeforcesApi() ratings = api.user_rating("VadVergasov") for rating in ratings: - assert type(rating.contest_id) is int - assert type(rating.contest_name) is str - assert type(rating.handle) is str - assert type(rating.rank) is int - assert type(rating.rating_update_time_seconds) is int - assert type(rating.old_rating) is int - assert type(rating.new_rating) is int + assert isinstance(rating.contest_id, int) + assert isinstance(rating.contest_name, str) + assert isinstance(rating.handle, str) + assert isinstance(rating.rank, int) + assert isinstance(rating.rating_update_time_seconds, int) + assert isinstance(rating.old_rating, int) + assert isinstance(rating.new_rating, int) def test_user_status(): api = CodeforcesApi() status = api.user_status("VadVergasov") for row in status: - assert type(row.id) is int - assert type(row.creation_time_seconds) is int - assert type(row.relative_time_seconds) is int - assert type(row.problem) is Problem - assert type(row.author) is Party - assert type(row.programming_language) is str - assert type(row.testset) is str - assert type(row.passed_test_count) is int - assert type(row.time_consumed_millis) is int - assert type(row.memory_consumed_bytes) is int - assert row.contest_id is None or type(row.contest_id) is int - assert row.verdict is None or type(row.verdict) is str - assert row.points is None or type(row.points) is float + assert isinstance(row.id, int) + assert isinstance(row.creation_time_seconds, int) + assert isinstance(row.relative_time_seconds, int) + assert isinstance(row.problem, Problem) + assert isinstance(row.author, Party) + assert isinstance(row.programming_language, str) + assert isinstance(row.testset, str) + assert isinstance(row.passed_test_count, int) + assert isinstance(row.time_consumed_millis, int) + assert isinstance(row.memory_consumed_bytes, int) + assert row.contest_id is None or isinstance(row.contest_id, int) + assert row.verdict is None or isinstance(row.verdict, str) + assert row.points is None or isinstance(row.points, float)