From abb42dcd4886705d6ba8af27f68ef605218ac67c Mon Sep 17 00:00:00 2001
From: Philip Paquette <pcpaquette@gmail.com>
Date: Wed, 11 Sep 2019 12:58:45 -0400
Subject: Added ReadtheDocs documentation for the public API

- Reformatted the docstring to be compatible
- Added tests to make sure the documentation compiles properly
- Added sphinx as a pip requirement

Co-authored-by: Philip Paquette <pcpaquette@gmail.com>
Co-authored-by: notoraptor <stevenbocco@gmail.com>
---
 diplomacy/integration/base_api.py                | 33 ++++++++----------------
 diplomacy/integration/webdiplomacy_net/api.py    | 25 +++++++++++++-----
 diplomacy/integration/webdiplomacy_net/game.py   | 32 +++++++++++++----------
 diplomacy/integration/webdiplomacy_net/orders.py | 15 +++++++----
 4 files changed, 58 insertions(+), 47 deletions(-)

(limited to 'diplomacy/integration')

diff --git a/diplomacy/integration/base_api.py b/diplomacy/integration/base_api.py
index c0dca4e..584310b 100644
--- a/diplomacy/integration/base_api.py
+++ b/diplomacy/integration/base_api.py
@@ -28,9 +28,13 @@ class BaseAPI(metaclass=ABCMeta):
 
     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
+            :type api_key: str
+            :type connect_timeout: int, optional
+            :type request_timeout: int, optional
         """
         self.api_key = api_key
         self.http_client = AsyncHTTPClient()
@@ -39,30 +43,14 @@ class BaseAPI(metaclass=ABCMeta):
 
     @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):
+    def get_game_and_power(self, *args, **kwargs):
         """ 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.
+            *Arguments are specific to each implementation.*
+
             :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
+
+                #. The diplomacy.Game object or None if an error occurred
+                #. The power name (e.g. 'FRANCE')
         """
         raise NotImplementedError()
 
@@ -70,6 +58,7 @@ class BaseAPI(metaclass=ABCMeta):
     @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'])
diff --git a/diplomacy/integration/webdiplomacy_net/api.py b/diplomacy/integration/webdiplomacy_net/api.py
index b4bde01..36b132c 100644
--- a/diplomacy/integration/webdiplomacy_net/api.py
+++ b/diplomacy/integration/webdiplomacy_net/api.py
@@ -39,8 +39,10 @@ class API(BaseAPI):
 
     @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
-            :return: List of GameIdCountryId tuples  [(game_id, country_id), (game_id, country_id)]
+        """ Lists the game on the standard map where a player is in CD (civil disorder)
+            and the bots needs to submit orders
+
+            :return: List of :class:`.GameIdCountryId` tuples  [(game_id, country_id), (game_id, country_id)]
         """
         route = 'players/cd'
         url = '%s?%s' % (API_WEBDIPLOMACY_NET, urlencode({'route': route}))
@@ -73,7 +75,8 @@ class API(BaseAPI):
     @gen.coroutine
     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)]
+
+            :return: List of :class:`.GameIdCountryId` tuples  [(game_id, country_id), (game_id, country_id)]
         """
         route = 'players/missing_orders'
         url = '%s?%s' % (API_WEBDIPLOMACY_NET, urlencode({'route': route}))
@@ -106,13 +109,19 @@ class API(BaseAPI):
     @gen.coroutine
     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.
+            :type game_id: int
+            :type country_id: int
+            :type max_phases: int | None, optional
             :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
+
+                #. The diplomacy.Game object from the game state or None if an error occurred
+                #. The power name (e.g. 'FRANCE') referred to by country_id
         """
+        # pylint: disable=arguments-differ
         route = 'game/status'
         url = '%s?%s' % (API_WEBDIPLOMACY_NET, urlencode({'route': route, 'gameID': game_id, 'countryID': country_id}))
         return_val = None, None
@@ -144,12 +153,16 @@ class API(BaseAPI):
     @gen.coroutine
     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 game: A :class:`diplomacy.engine.game.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
+            :type power_name: str
+            :type orders: List[str]
+            :type wait: bool | None, optional
         """
         # Logging orders
         LOGGER.info('[%s/%s/%s] - Submitting orders: %s', game.game_id, game.get_current_phase(), power_name, orders)
diff --git a/diplomacy/integration/webdiplomacy_net/game.py b/diplomacy/integration/webdiplomacy_net/game.py
index 0233ea9..a89933c 100644
--- a/diplomacy/integration/webdiplomacy_net/game.py
+++ b/diplomacy/integration/webdiplomacy_net/game.py
@@ -18,9 +18,7 @@ LOGGER = logging.getLogger(__name__)
 
 
 def turn_to_phase(turn, phase):
-    """ Converts a turn and phase to a short phase name
-        e.g. turn 1 - phase 'Retreats' to 'F1901R'
-    """
+    """ Converts a turn and phase to a short phase name e.g. turn 1 - phase 'Retreats' to 'F1901R' """
     year = 1901 + turn // 2
     season = 'S' if turn % 2 == 0 else 'F'
     if phase == 'Builds':
@@ -36,13 +34,14 @@ def turn_to_phase(turn, phase):
 #  'retreating': 'Yes'/'No'}
 def unit_dict_to_str(unit_dict, map_id=1):
     """ Converts a unit from the dictionary format to the string format
-        e.g. {'unitType': 'Army', 'terrID': 6, 'countryId': 1, 'retreating': 'No'}
-             to 'ENGLAND', 'A LON'
+        e.g. ``{'unitType': 'Army', 'terrID': 6, 'countryId': 1, 'retreating': 'No'}``
+        to ``'ENGLAND', 'A LON'``
 
         :param unit_dict: The unit in dictionary format from webdiplomacy.net
         :return: A tuple consisting of:
-            1) The power owning the unit (e.g. 'FRANCE')
-            2) The unit in string format (with a leading * when dislodged) (e.g. '*A PAR')
+
+            #. The power owning the unit (e.g. 'FRANCE')
+            #. The unit in string format (with a leading ``*`` when dislodged) (e.g. ``'*A PAR'``)
     """
     req_fields = ('unitType', 'terrID', 'countryID', 'retreating')
     if [1 for field in req_fields if field not in unit_dict]:
@@ -84,12 +83,13 @@ def unit_dict_to_str(unit_dict, map_id=1):
 #  'countryId':  integer}
 def center_dict_to_str(center_dict, map_id=1):
     """ Converts a supply center from the dictionary format to the string format
-        e.g. {'terrID': 6, 'countryId': 1} to 'ENGLAND', 'LON'
+        e.g. ``{'terrID': 6, 'countryId': 1}`` to ``'ENGLAND', 'LON'``
 
         :param center_dict: The center in dictionary format from webdiplomacy.net
         :return: A tuple consisting of:
-            1) The power owning the center (e.g. 'FRANCE')
-            2) The location where the supply center is (e.g. 'PAR')
+
+            #. The power owning the center (e.g. 'FRANCE')
+            #. The location where the supply center is (e.g. 'PAR')
     """
     req_fields = ('terrID', 'countryID')
     if [1 for field in req_fields if field not in center_dict]:
@@ -132,11 +132,13 @@ def center_dict_to_str(center_dict, map_id=1):
 #  'dislodged':  'Yes', 'No'}
 def order_dict_to_str(order_dict, phase, map_id=1):
     """ Converts an order from the dictionary format to the string format
+
         :param order_dict: The order in dictionary format from webdiplomacy.net
         :param phase: The current phase ('Diplomacy', 'Retreats', 'Builds')
         :return: A tuple consisting of:
-            1) The power who submitted the order (e.g. 'FRANCE')
-            2) The order in string format (e.g. 'A PAR H')
+
+            #. The power who submitted the order (e.g. 'FRANCE')
+            #. The order in string format (e.g. 'A PAR H')
     """
     req_fields = ('countryID',)
     if [1 for field in req_fields if field not in order_dict]:
@@ -223,12 +225,14 @@ def process_phase_dict(phase_dict, map_id=1):
 #  'standoffs':   []}
 def state_dict_to_game_and_power(state_dict, country_id, max_phases=None):
     """ Converts a game state from the dictionary format to an actual diplomacy.Game object with the related power.
+
         :param state_dict: The game state in dictionary format from webdiplomacy.net
         :param country_id: The country id we want to convert.
         :param max_phases: Optional. If set, improve speed by only keeping the last 'x' phases to regenerate the game.
         :return: A tuple of
-            1) None, None       - on error or if the conversion is not possible, or game is invalid / not-started / done
-            2) game, power_name - on successful conversion
+
+            #. None, None       - on error or if the conversion is not possible, or game is invalid / not-started / done
+            #. game, power_name - on successful conversion
     """
     if state_dict is None:
         return None, None
diff --git a/diplomacy/integration/webdiplomacy_net/orders.py b/diplomacy/integration/webdiplomacy_net/orders.py
index afacf03..8fa966c 100644
--- a/diplomacy/integration/webdiplomacy_net/orders.py
+++ b/diplomacy/integration/webdiplomacy_net/orders.py
@@ -18,9 +18,10 @@ LOGGER = logging.getLogger(__name__)
 
 def is_adjacent_for_convoy(loc_1, loc_2, map_object):
     """ Checks if two locations are adjacent (for convoy purposes)
-            - If loc_1 and loc_2 are water, loc_1 and loc_2 must be adjacent
-            - If loc_1 or loc_2 is land, then they are not adjacent
-            - If loc_1 or loc_2 are coast, then the other locations needs to be a water loc at most 1 loc away
+
+        - If loc_1 and loc_2 are water, loc_1 and loc_2 must be adjacent
+        - If loc_1 or loc_2 is land, then they are not adjacent
+        - If loc_1 or loc_2 are coast, then the other locations needs to be a water loc at most 1 loc away
 
         :type map_object: diplomacy.Map
     """
@@ -48,6 +49,7 @@ def is_adjacent_for_convoy(loc_1, loc_2, map_object):
 
 def find_convoy_path(src, dest, map_object, game=None, including=None, excluding=None):
     """ Finds a convoy path from src to dest
+
         :param src: The source location (e.g. 'BRE')
         :param dest: The destination location (e.g. 'LON')
         :param map_object: A diplomacy.Map object representation of the current map
@@ -55,7 +57,7 @@ def find_convoy_path(src, dest, map_object, game=None, including=None, excluding
         :param including: Optional. A single province (e.g. 'NAO') or a list of provinces that must be in the path.
         :param excluding: Optional. A single province (e.g. 'NAO') or a list of provinces that must NOT be in the path.
         :return: Either an empty list if a convoy is not possible between src and dest
-                 or a list of [src, fleet1, fleet2, ..., fleet_n, dest] to use to convoy A `src` - `dest`.
+             or a list of [src, fleet1, fleet2, ..., fleet_n, dest] to use to convoy A `src` - `dest`.
         :type map_object: diplomacy.Map
         :type game: diplomacy.Game
     """
@@ -122,11 +124,12 @@ def find_convoy_path(src, dest, map_object, game=None, including=None, excluding
     return []
 
 
-class Order():
+class Order:
     """ Class to convert order from string representation to dictionary (webdiplomacy.net) representation """
 
     def __init__(self, order, map_id=None, map_name=None, phase_type=None, game=None):
         """ Constructor
+
             :param order: An order (either as a string 'A PAR H' or as a dictionary)
             :param map_id: Optional. The map id of the map where orders are submitted (webdiplomacy format)
             :param map_name: Optional. The map name of the map where orders are submitted.
@@ -162,6 +165,7 @@ class Order():
 
     def _build_from_string(self, order, game=None):
         """ Builds this object from a string
+
             :type order: str
             :type game: diplomacy.Game
         """
@@ -444,6 +448,7 @@ class Order():
 
     def _build_from_dict(self, order):
         """ Builds this object from a dictionary
+
             :type order: dict
         """
         # pylint: disable=too-many-return-statements
-- 
cgit v1.2.3