From 8371e007c804ea76248ac6e7bb1a8d5804928864 Mon Sep 17 00:00:00 2001 From: Philip Paquette Date: Fri, 9 Aug 2019 11:20:31 -0400 Subject: [API] Implemented an abstract BaseAPI class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- diplomacy/integration/base_api.py | 80 +++++++++++++++++++++++++++ diplomacy/integration/webdiplomacy_net/api.py | 16 +----- 2 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 diplomacy/integration/base_api.py (limited to 'diplomacy') diff --git a/diplomacy/integration/base_api.py b/diplomacy/integration/base_api.py new file mode 100644 index 0000000..c0dca4e --- /dev/null +++ b/diplomacy/integration/base_api.py @@ -0,0 +1,80 @@ +# ============================================================================== +# Copyright (C) 2019 - Philip Paquette +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +# ============================================================================== +""" Contains the base API class """ +from abc import ABCMeta, abstractmethod +import logging +from tornado import gen +from tornado.httpclient import AsyncHTTPClient + +# Constants +LOGGER = logging.getLogger(__name__) + +class BaseAPI(metaclass=ABCMeta): + """ Base API class """ + + def __init__(self, api_key, connect_timeout=30, request_timeout=60): + """ Constructor + :param api_key: The API key to use for sending API requests + :param connect_timeout: The maximum amount of time to wait for the connection to be established + :param request_timeout: The maximum amount of time to wait for the request to be processed + """ + self.api_key = api_key + self.http_client = AsyncHTTPClient() + self.connect_timeout = connect_timeout + self.request_timeout = request_timeout + + @gen.coroutine + @abstractmethod + def list_games_with_players_in_cd(self): + """ Lists the game on the standard map where a player is in CD and the bots needs to submit orders + :return: List of GameIdCountryId tuples [(game_id, country_id), (game_id, country_id)] + """ + raise NotImplementedError() + + @gen.coroutine + @abstractmethod + def list_games_with_missing_orders(self): + """ Lists of the game on the standard where the user has not submitted orders yet. + :return: List of GameIdCountryId tuples [(game_id, country_id), (game_id, country_id)] + """ + raise NotImplementedError() + + @gen.coroutine + @abstractmethod + def get_game_and_power(self, game_id, country_id, max_phases=None): + """ Returns the game and the power we are playing + :param game_id: The id of the game object (integer) + :param country_id: The id of the country for which we want the game state (integer) + :param max_phases: Optional. If set, improve speed by generating game only using the last 'x' phases. + :return: A tuple consisting of + 1) The diplomacy.Game object from the game state or None if an error occurred + 2) The power name (e.g. 'FRANCE') referred to by country_id + """ + raise NotImplementedError() + + @gen.coroutine + @abstractmethod + def set_orders(self, game, power_name, orders, wait=None): + """ Submits orders back to the server + :param game: A diplomacy.Game object representing the current state of the game + :param power_name: The name of the power submitting the orders (e.g. 'FRANCE') + :param orders: A list of strings representing the orders (e.g. ['A PAR H', 'F BRE - MAO']) + :param wait: Optional. If True, sets ready=False, if False sets ready=True. + :return: True for success, False for failure + :type game: diplomacy.Game + """ + raise NotImplementedError() diff --git a/diplomacy/integration/webdiplomacy_net/api.py b/diplomacy/integration/webdiplomacy_net/api.py index 75e0265..200487d 100644 --- a/diplomacy/integration/webdiplomacy_net/api.py +++ b/diplomacy/integration/webdiplomacy_net/api.py @@ -20,7 +20,8 @@ import os from urllib.parse import urlencode import ujson as json from tornado import gen -from tornado.httpclient import AsyncHTTPClient, HTTPRequest +from tornado.httpclient import HTTPRequest +from diplomacy.integration.base_api import BaseAPI from diplomacy.integration.webdiplomacy_net.game import state_dict_to_game_and_power from diplomacy.integration.webdiplomacy_net.orders import Order from diplomacy.integration.webdiplomacy_net.utils import CACHE, GameIdCountryId @@ -30,20 +31,9 @@ LOGGER = logging.getLogger(__name__) API_USER_AGENT = 'KestasBot / Philip Paquette v1.0' API_WEBDIPLOMACY_NET = os.environ.get('API_WEBDIPLOMACY', 'https://webdiplomacy.net/api.php') -class API(): +class API(BaseAPI): """ API to interact with webdiplomacy.net """ - def __init__(self, api_key, connect_timeout=30, request_timeout=60): - """ Constructor - :param api_key: The API key to use for sending API requests - :param connect_timeout: The maximum amount of time to wait for the connection to be established - :param request_timeout: The maximum amount of time to wait for the request to be processed - """ - self.api_key = api_key - self.http_client = AsyncHTTPClient() - self.connect_timeout = connect_timeout - self.request_timeout = request_timeout - @gen.coroutine def list_games_with_players_in_cd(self): """ Lists the game on the standard map where a player is in CD and the bots needs to submit orders -- cgit v1.2.3