Browse Source

Change order of documentation by source declaration.

pull/77/merge
Rapptz 9 years ago
parent
commit
af94179be5
  1. 356
      discord/client.py
  2. 2
      docs/conf.py

356
discord/client.py

@ -411,7 +411,184 @@ class Client:
log.info('sending reconnection frame to websocket {}'.format(payload))
yield from self.ws.send(utils.to_json(payload))
# properties
# login state management
@asyncio.coroutine
def login(self, email, password):
"""|coro|
Logs in the client with the specified credentials.
Parameters
----------
email : str
The email used to login.
password : str
The password used to login.
Raises
------
LoginFailure
The wrong credentials are passed.
HTTPException
An unknown HTTP related error occurred,
usually when it isn't 200 or the known incorrect credentials
passing status code.
"""
# attempt to read the token from cache
if self.cache_auth:
yield from self._login_via_cache(email, password)
if self.is_logged_in:
return
payload = {
'email': email,
'password': password
}
data = utils.to_json(payload)
resp = yield from aiohttp.post(endpoints.LOGIN, data=data, headers=self.headers, loop=self.loop)
log.debug(request_logging_format.format(method='POST', response=resp))
if resp.status != 200:
yield from resp.release()
if resp.status == 400:
raise LoginFailure('Improper credentials have been passed.')
else:
raise HTTPException(resp, None)
log.info('logging in returned status code {}'.format(resp.status))
self.email = email
body = yield from resp.json()
self.token = body['token']
self.headers['authorization'] = self.token
self._is_logged_in.set()
# since we went through all this trouble
# let's make sure we don't have to do it again
if self.cache_auth:
self._update_cache(email, password)
@asyncio.coroutine
def logout(self):
"""|coro|
Logs out of Discord and closes all connections."""
response = yield from aiohttp.post(endpoints.LOGOUT, headers=self.headers, loop=self.loop)
yield from response.release()
yield from self.close()
self._is_logged_in.clear()
log.debug(request_logging_format.format(method='POST', response=response))
@asyncio.coroutine
def connect(self):
"""|coro|
Creates a websocket connection and connects to the websocket listen
to messages from discord.
This function is implemented using a while loop in the background.
If you need to run this event listening in another thread then
you should run it in an executor or schedule the coroutine to
be executed later using ``loop.create_task``.
Raises
-------
ClientException
If this is called before :meth:`login` was invoked successfully
or when an unexpected closure of the websocket occurs.
GatewayNotFound
If the gateway to connect to discord is not found. Usually if this
is thrown then there is a discord API outage.
"""
self.gateway = yield from self._get_gateway()
yield from self._make_websocket()
while not self.is_closed:
msg = yield from self.ws.recv()
if msg is None:
if self.ws.close_code == 1012:
yield from self.redirect_websocket(self.gateway)
continue
elif not self._is_ready.is_set():
raise ClientException('Unexpected websocket closure received')
else:
yield from self.close()
break
yield from self.received_message(msg)
@asyncio.coroutine
def close(self):
"""Closes the websocket connection.
To reconnect the websocket connection, :meth:`connect` must be used.
"""
if self.is_closed:
return
if self.is_voice_connected():
yield from self.voice.disconnect()
self.voice = None
if self.ws.open:
yield from self.ws.close()
self.keep_alive.cancel()
self._closed.set()
self._is_ready.clear()
@asyncio.coroutine
def start(self, email, password):
"""|coro|
A shorthand coroutine for :meth:`login` + :meth:`connect`.
"""
yield from self.login(email, password)
yield from self.connect()
def run(self, email, password):
"""A blocking call that abstracts away the `event loop`_
initialisation from you.
If you want more control over the event loop then this
function should not be used. Use :meth:`start` coroutine
or :meth:`connect` + :meth:`login`.
Roughly Equivalent to: ::
try:
loop.run_until_complete(start(email, password))
except KeyboardInterrupt:
loop.run_until_complete(logout())
# cancel all tasks lingering
finally:
loop.close()
Warning
--------
This function must be the last function to call due to the fact that it
is blocking. That means that registration of events or anything being
called after this function call will not execute until it returns.
"""
try:
self.loop.run_until_complete(self.start(email, password))
except KeyboardInterrupt:
self.loop.run_until_complete(self.logout())
pending = asyncio.Task.all_tasks()
gathered = asyncio.gather(*pending)
try:
gathered.cancel()
self.loop.run_forever()
gathered.exception()
except:
pass
finally:
self.loop.close()
# properties
@property
def is_logged_in(self):
@ -605,183 +782,6 @@ class Client:
message = None
return message
# login state management
@asyncio.coroutine
def login(self, email, password):
"""|coro|
Logs in the client with the specified credentials.
Parameters
----------
email : str
The email used to login.
password : str
The password used to login.
Raises
------
LoginFailure
The wrong credentials are passed.
HTTPException
An unknown HTTP related error occurred,
usually when it isn't 200 or the known incorrect credentials
passing status code.
"""
# attempt to read the token from cache
if self.cache_auth:
yield from self._login_via_cache(email, password)
if self.is_logged_in:
return
payload = {
'email': email,
'password': password
}
data = utils.to_json(payload)
resp = yield from aiohttp.post(endpoints.LOGIN, data=data, headers=self.headers, loop=self.loop)
log.debug(request_logging_format.format(method='POST', response=resp))
if resp.status != 200:
yield from resp.release()
if resp.status == 400:
raise LoginFailure('Improper credentials have been passed.')
else:
raise HTTPException(resp, None)
log.info('logging in returned status code {}'.format(resp.status))
self.email = email
body = yield from resp.json()
self.token = body['token']
self.headers['authorization'] = self.token
self._is_logged_in.set()
# since we went through all this trouble
# let's make sure we don't have to do it again
if self.cache_auth:
self._update_cache(email, password)
@asyncio.coroutine
def logout(self):
"""|coro|
Logs out of Discord and closes all connections."""
response = yield from aiohttp.post(endpoints.LOGOUT, headers=self.headers, loop=self.loop)
yield from response.release()
yield from self.close()
self._is_logged_in.clear()
log.debug(request_logging_format.format(method='POST', response=response))
@asyncio.coroutine
def connect(self):
"""|coro|
Creates a websocket connection and connects to the websocket listen
to messages from discord.
This function is implemented using a while loop in the background.
If you need to run this event listening in another thread then
you should run it in an executor or schedule the coroutine to
be executed later using ``loop.create_task``.
Raises
-------
ClientException
If this is called before :meth:`login` was invoked successfully
or when an unexpected closure of the websocket occurs.
GatewayNotFound
If the gateway to connect to discord is not found. Usually if this
is thrown then there is a discord API outage.
"""
self.gateway = yield from self._get_gateway()
yield from self._make_websocket()
while not self.is_closed:
msg = yield from self.ws.recv()
if msg is None:
if self.ws.close_code == 1012:
yield from self.redirect_websocket(self.gateway)
continue
elif not self._is_ready.is_set():
raise ClientException('Unexpected websocket closure received')
else:
yield from self.close()
break
yield from self.received_message(msg)
@asyncio.coroutine
def close(self):
"""Closes the websocket connection.
To reconnect the websocket connection, :meth:`connect` must be used.
"""
if self.is_closed:
return
if self.is_voice_connected():
yield from self.voice.disconnect()
self.voice = None
if self.ws.open:
yield from self.ws.close()
self.keep_alive.cancel()
self._closed.set()
self._is_ready.clear()
@asyncio.coroutine
def start(self, email, password):
"""|coro|
A shorthand coroutine for :meth:`login` + :meth:`connect`.
"""
yield from self.login(email, password)
yield from self.connect()
def run(self, email, password):
"""A blocking call that abstracts away the `event loop`_
initialisation from you.
If you want more control over the event loop then this
function should not be used. Use :meth:`start` coroutine
or :meth:`connect` + :meth:`login`.
Roughly Equivalent to: ::
try:
loop.run_until_complete(start(email, password))
except KeyboardInterrupt:
loop.run_until_complete(logout())
# cancel all tasks lingering
finally:
loop.close()
Warning
--------
This function must be the last function to call due to the fact that it
is blocking. That means that registration of events or anything being
called after this function call will not execute until it returns.
"""
try:
self.loop.run_until_complete(self.start(email, password))
except KeyboardInterrupt:
self.loop.run_until_complete(self.logout())
pending = asyncio.Task.all_tasks()
gathered = asyncio.gather(*pending)
try:
gathered.cancel()
self.loop.run_forever()
gathered.exception()
except:
pass
finally:
self.loop.close()
# event registration
def event(self, coro):

2
docs/conf.py

@ -35,6 +35,8 @@ extensions = [
'sphinx.ext.napoleon',
]
autodoc_member_order = 'bysource'
extlinks = {
'issue': ('https://github.com/Rapptz/discord.py/issues/%s', 'issue '),
}

Loading…
Cancel
Save