From abb42dcd4886705d6ba8af27f68ef605218ac67c Mon Sep 17 00:00:00 2001 From: Philip Paquette 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 Co-authored-by: notoraptor --- diplomacy/client/channel.py | 134 ++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 53 deletions(-) (limited to 'diplomacy/client/channel.py') diff --git a/diplomacy/client/channel.py b/diplomacy/client/channel.py index 0403e7f..146d5e3 100644 --- a/diplomacy/client/channel.py +++ b/diplomacy/client/channel.py @@ -15,6 +15,7 @@ # with this program. If not, see . # ============================================================================== """ Channel + - The channel object represents an authenticated connection over a socket. - It has a token that it sends with every request to authenticate itself. """ @@ -23,21 +24,26 @@ import logging from tornado import gen from diplomacy.communication import requests -from diplomacy.utils import strings +from diplomacy.utils import strings, common LOGGER = logging.getLogger(__name__) -def req_fn(request_class, local_req_fn=None, **request_args): +def _req_fn(request_class, local_req_fn=None, **request_args): """ Create channel request method that sends request with channel token. + :param request_class: class of request to send with channel request method. :param local_req_fn: (optional) Channel method to use locally to try retrieving a data instead of sending a request. If provided, local_req_fn is called with request args: + - if it returns anything else than None, then returned data is returned by channel request method. - else, request class is still sent and channel request method follows standard path (request sent, response received, response handler called and final handler result returned). + :param request_args: arguments to pass to request class to create the request object. :return: a Channel method. """ + str_params = (', '.join('%s=%s' % (key, common.to_string(value)) + for (key, value) in sorted(request_args.items()))) if request_args else '' @gen.coroutine def func(self, game_object=None, **kwargs): @@ -67,29 +73,51 @@ def req_fn(request_class, local_req_fn=None, **request_args): request = request_class(**kwargs) return (yield self.connection.send(request, game_object)) + func.__request_name__ = request_class.__name__ + func.__request_params__ = str_params + func.__doc__ = """ + Send request :class:`.%(request_name)s`%(with_params)s``kwargs``. + Return response data returned by server for this request. + See :class:`.%(request_name)s` about request parameters and response. + """ % {'request_name': request_class.__name__, + 'with_params': ' with forced parameters ``(%s)`` and additional request parameters ' + % str_params if request_args else ' with request parameters '} return func -class Channel(): +class Channel: """ Channel - Represents an authenticated connection over a physical socket """ + # pylint: disable=too-few-public-methods __slots__ = ['connection', 'token', 'game_id_to_instances', '__weakref__'] def __init__(self, connection, token): """ Initialize a channel. + + Properties: + + - **connection**: :class:`.Connection` object from which this channel originated. + - **token**: Channel token, used to identify channel on server. + - **game_id_to_instances**: Dictionary mapping a game ID to :class:`.NetworkGame` objects loaded for this + game. Each :class:`.NetworkGame` has a specific role, which is either an observer role, an omniscient + role, or a power (player) role. Network games for a specific game ID are managed within a + :class:`.GameInstancesSet`, which makes sure that there will be at most 1 :class:`.NetworkGame` instance + per possible role. + :param connection: a Connection object. :param token: Channel token. - :type connection: diplomacy.Connection + :type connection: diplomacy.client.connection.Connection + :type token: str """ self.connection = connection self.token = token self.game_id_to_instances = {} # {game id => GameInstances} - def local_join_game(self, **kwargs): + def _local_join_game(self, **kwargs): """ Look for a local game with given kwargs intended to be used to build a JoinGame request. Return None if no local game found, else local game found. - Game is identified with game ID and power name (optional). + Game is identified with game ID **(required)** and power name *(optional)*. If power name is None, we look for a "special" game (observer or omniscient game) - loaded locally. Note that there is at most 1 special game per channel + game ID: - either observer or omniscient, not both. + loaded locally. Note that there is at most 1 special game per (channel + game ID) + couple: either observer or omniscient, not both. """ game_id = kwargs[strings.GAME_ID] power_name = kwargs.get(strings.POWER_NAME, None) @@ -103,54 +131,54 @@ class Channel(): # Public channel API. # =================== - create_game = req_fn(requests.CreateGame) - get_available_maps = req_fn(requests.GetAvailableMaps) - get_playable_powers = req_fn(requests.GetPlayablePowers) - join_game = req_fn(requests.JoinGame, local_req_fn=local_join_game) - join_powers = req_fn(requests.JoinPowers) - list_games = req_fn(requests.ListGames) - get_games_info = req_fn(requests.GetGamesInfo) + create_game = _req_fn(requests.CreateGame) + get_available_maps = _req_fn(requests.GetAvailableMaps) + get_playable_powers = _req_fn(requests.GetPlayablePowers) + join_game = _req_fn(requests.JoinGame, local_req_fn=_local_join_game) + join_powers = _req_fn(requests.JoinPowers) + list_games = _req_fn(requests.ListGames) + get_games_info = _req_fn(requests.GetGamesInfo) + get_dummy_waiting_powers = _req_fn(requests.GetDummyWaitingPowers) # User Account API. - delete_account = req_fn(requests.DeleteAccount) - logout = req_fn(requests.Logout) + delete_account = _req_fn(requests.DeleteAccount) + logout = _req_fn(requests.Logout) # Admin / Moderator API. - make_omniscient = req_fn(requests.SetGrade, grade=strings.OMNISCIENT, grade_update=strings.PROMOTE) - remove_omniscient = req_fn(requests.SetGrade, grade=strings.OMNISCIENT, grade_update=strings.DEMOTE) - promote_administrator = req_fn(requests.SetGrade, grade=strings.ADMIN, grade_update=strings.PROMOTE) - demote_administrator = req_fn(requests.SetGrade, grade=strings.ADMIN, grade_update=strings.DEMOTE) - promote_moderator = req_fn(requests.SetGrade, grade=strings.MODERATOR, grade_update=strings.PROMOTE) - demote_moderator = req_fn(requests.SetGrade, grade=strings.MODERATOR, grade_update=strings.DEMOTE) - - # ================ - # Public game API. - # ================ - - get_dummy_waiting_powers = req_fn(requests.GetDummyWaitingPowers) - get_phase_history = req_fn(requests.GetPhaseHistory) - leave_game = req_fn(requests.LeaveGame) - send_game_message = req_fn(requests.SendGameMessage) - set_orders = req_fn(requests.SetOrders) - - clear_centers = req_fn(requests.ClearCenters) - clear_orders = req_fn(requests.ClearOrders) - clear_units = req_fn(requests.ClearUnits) - - wait = req_fn(requests.SetWaitFlag, wait=True) - no_wait = req_fn(requests.SetWaitFlag, wait=False) - vote = req_fn(requests.Vote) - save = req_fn(requests.SaveGame) - synchronize = req_fn(requests.Synchronize) + make_omniscient = _req_fn(requests.SetGrade, grade=strings.OMNISCIENT, grade_update=strings.PROMOTE) + remove_omniscient = _req_fn(requests.SetGrade, grade=strings.OMNISCIENT, grade_update=strings.DEMOTE) + promote_administrator = _req_fn(requests.SetGrade, grade=strings.ADMIN, grade_update=strings.PROMOTE) + demote_administrator = _req_fn(requests.SetGrade, grade=strings.ADMIN, grade_update=strings.DEMOTE) + promote_moderator = _req_fn(requests.SetGrade, grade=strings.MODERATOR, grade_update=strings.PROMOTE) + demote_moderator = _req_fn(requests.SetGrade, grade=strings.MODERATOR, grade_update=strings.DEMOTE) + + # ==================================================================== + # Game API. Intended to be called by NetworkGame object, not directly. + # ==================================================================== + + _get_phase_history = _req_fn(requests.GetPhaseHistory) + _leave_game = _req_fn(requests.LeaveGame) + _send_game_message = _req_fn(requests.SendGameMessage) + _set_orders = _req_fn(requests.SetOrders) + + _clear_centers = _req_fn(requests.ClearCenters) + _clear_orders = _req_fn(requests.ClearOrders) + _clear_units = _req_fn(requests.ClearUnits) + + _wait = _req_fn(requests.SetWaitFlag, wait=True) + _no_wait = _req_fn(requests.SetWaitFlag, wait=False) + _vote = _req_fn(requests.Vote) + _save = _req_fn(requests.SaveGame) + _synchronize = _req_fn(requests.Synchronize) # Admin / Moderator API. - delete_game = req_fn(requests.DeleteGame) - kick_powers = req_fn(requests.SetDummyPowers) - set_state = req_fn(requests.SetGameState) - process = req_fn(requests.ProcessGame) - query_schedule = req_fn(requests.QuerySchedule) - start = req_fn(requests.SetGameStatus, status=strings.ACTIVE) - pause = req_fn(requests.SetGameStatus, status=strings.PAUSED) - resume = req_fn(requests.SetGameStatus, status=strings.ACTIVE) - cancel = req_fn(requests.SetGameStatus, status=strings.CANCELED) - draw = req_fn(requests.SetGameStatus, status=strings.COMPLETED) + _delete_game = _req_fn(requests.DeleteGame) + _kick_powers = _req_fn(requests.SetDummyPowers) + _set_state = _req_fn(requests.SetGameState) + _process = _req_fn(requests.ProcessGame) + _query_schedule = _req_fn(requests.QuerySchedule) + _start = _req_fn(requests.SetGameStatus, status=strings.ACTIVE) + _pause = _req_fn(requests.SetGameStatus, status=strings.PAUSED) + _resume = _req_fn(requests.SetGameStatus, status=strings.ACTIVE) + _cancel = _req_fn(requests.SetGameStatus, status=strings.CANCELED) + _draw = _req_fn(requests.SetGameStatus, status=strings.COMPLETED) -- cgit v1.2.3