Skip to content

Commit

Permalink
remove pyswagger; add ErrorResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
deluxghost committed Nov 2, 2018
1 parent 19e58b9 commit 593b401
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 49 deletions.
2 changes: 1 addition & 1 deletion ASF/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = '2.0.0'
__version__ = '2.1.0'

from .models import IPC # noqa: F401
78 changes: 50 additions & 28 deletions ASF/models.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import asyncio

import aiohttp
import pyswagger

from . import utils


class IPC:

def __init__(self, ipc='http://127.0.0.1:1242/', password='', timeout=5):
def __init__(self, ipc='http://127.0.0.1:1242/', password='', timeout=10):
self._ipc = ipc
self._password = password
self._timeout = timeout

async def __aenter__(self):
self._swagger = pyswagger.App.create(utils.build_url(self._ipc, '/swagger/ASF/swagger.json'))
for api in self._swagger.op.values():
headers = dict()
if self._password:
headers['Authentication'] = self._password
timeout = aiohttp.ClientTimeout(total=self._timeout)
self._session = aiohttp.ClientSession(headers=headers, timeout=timeout)
try:
async with self._session.get(utils.build_url(self._ipc, '/swagger/ASF/swagger.json')) as resp:
self._swagger = await resp.json()
except Exception:
await self._session.close()
raise
for path in self._swagger['paths'].keys():
p = self
p_path = ''
for node in api.path.strip(utils.sep).split(utils.sep):
for node in path.strip(utils.sep).split(utils.sep):
p_path += f'/{node}'
if node.startswith('{') and node.endswith('}'):
arg = node[1:-1]
Expand All @@ -27,11 +38,6 @@ async def __aenter__(self):
setattr(p, node, Endpoint(self))
p = getattr(p, node)
p._path = p_path
headers = dict()
if self._password:
headers['Authentication'] = self._password
timeout = aiohttp.ClientTimeout(total=self._timeout)
self._session = aiohttp.ClientSession(headers=headers, timeout=timeout)
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
Expand All @@ -57,30 +63,36 @@ async def _request(self, method, body=None, params=None, **kw):
url = utils.build_url(self._ipc._ipc, self._path)
for k, v in kw.items():
url = url.replace(f'{{{k}}}', utils.quote(v))
async with session.request(method, url, json=body, params=params) as resp:
try:
json_data = await resp.json()
except Exception:
json_data = None
text = await resp.text()
return ASFResponse(resp, json_data, text)
try:
async with session.request(method, url, json=body, params=params) as resp:
try:
json_data = await resp.json()
except Exception:
json_data = None
text = await resp.text()
return ASFResponse(resp, json_data, text)
except (asyncio.TimeoutError, aiohttp.ClientError) as exc:
return ErrorResponse(url, exc.__class__.__name__)

async def ws(self, **kw):
session = self._ipc._session
url = utils.build_url(self._ipc._ipc, self._path)
for k, v in kw.items():
url = url.replace(f'{{{k}}}', utils.quote(v))
async with session.ws_connect(url) as ws:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
try:
json_data = msg.json()
except Exception:
json_data = None
text = msg.data
yield WSResponse(url, json_data, text)
elif msg.type == aiohttp.WSMsgType.ERROR or msg.type == aiohttp.WSMsgType.CLOSE:
break
try:
async with session.ws_connect(url) as ws:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
try:
json_data = msg.json()
except Exception:
json_data = None
text = msg.data
yield WSResponse(url, json_data, text)
elif msg.type == aiohttp.WSMsgType.ERROR or msg.type == aiohttp.WSMsgType.CLOSE:
break
except (asyncio.TimeoutError, aiohttp.ClientError) as exc:
yield ErrorResponse(url, exc.__class__.__name__)

async def get(self, **kw):
return await self._request('get', **kw)
Expand Down Expand Up @@ -135,3 +147,13 @@ def __init__(self, resp, json_data, text):
self.Message = self.message
self.Result = self.result
self.Success = self.success


class ErrorResponse:

def __init__(self, url, message):
self.url = url
self.OK = self.ok = False
self.Message = self.message = message
self.Result = self.result = None
self.Success = self.success = False
57 changes: 39 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ This example shows how to send a command to ASF:
import asyncio
from ASF import IPC

async def command(cmd):
async def command(asf, cmd):
return await asf.Api.Command['command'].post(command=cmd)

async def main():
# The IPC initialization time depends on the network
async with IPC(ipc='http://127.0.0.1:1242', password='YOUR IPC PASSWORD') as asf:
resp = await asf.Api.Command['command'].post(command=cmd)
return resp.result
while True:
cmd = input('Enter a command: ')
resp = await command(asf, cmd)
if resp.success:
print(resp.result)
else:
print(f'Error: {resp.message}')

cmd = input('Enter a command: ')
loop = asyncio.get_event_loop()
output = loop.run_until_complete(command(cmd))
print(output)
output = loop.run_until_complete(main())
loop.close()
```

Expand All @@ -51,15 +58,16 @@ To get a list of all endpoints of ASF, open your web browser and visit the swagg

You can see many endpoints with their path, such as `/Api/Bot/{botNames}`, this endpoint in ASF_IPC is `asf.Api.Bot['botNames']`.

The replacing rules are simple: change `/` to `.` and change `/{variable}`

Some more examples:

```python
async with IPC(...) as asf:
asf.Api.ASF # /Api/ASF
asf.Api.Command['command'] # /Api/Command/{command}
asf.Api.Bot['botNames'].Pause # /Api/Bot/{botNames}/Pause
asf.Api.WWW.GitHub.Releases # /Api/WWW/GitHub/Releases
asf.Api.WWW.GitHub.Releases['version'] # /Api/WWW/GitHub/Releases/{version}
asf.Api.ASF # /Api/ASF
asf.Api.Command['command'] # /Api/Command/{command}
asf.Api.Bot['botNames'].Pause # /Api/Bot/{botNames}/Pause
asf.Api.WWW.GitHub.Releases # /Api/WWW/GitHub/Releases
asf.Api.WWW.GitHub.Releases['version'] # /Api/WWW/GitHub/Releases/{version}
```

## Send a request
Expand All @@ -75,11 +83,11 @@ Some examples:

```python
# POST /Api/Command/status%20asf
resp = await asf.Api.Command['command'].post(command='status asf')
await asf.Api.Command['command'].post(command='status asf')
# GET /Api/WWW/GitHub/Releases?count=10
resp = await asf.Api.WWW.GitHub.Releases.get(params={'count': 10})
await asf.Api.WWW.GitHub.Releases.get(params={'count': 10})
# POST /Api/Bot/robot with json body {'BotConfig': ...}
resp = await asf.Api.Bot['botName'].post(body={'BotConfig': ...}, botName='robot')
await asf.Api.Bot['botName'].post(body={'BotConfig': ...}, botName='robot')
```

## Get a response
Expand All @@ -97,8 +105,21 @@ If ASF_IPC cannot give a value to some attributes, these attributes will be `Non
Example for `/Api/NLog`:

```python
async def get_log():
async with IPC(ipc='http://127.0.0.1:1242', password='YOUR IPC PASSWORD') as asf:
async for resp in asf.Api.NLog.ws(): # use ws() instead of get(), post()...
import asyncio
from ASF import IPC

async def get_log(asf):
async for resp in asf.Api.NLog.ws(): # use ws() instead of get(), post()...
if resp.success:
print(resp.result)

async def main():
async with IPC(ipc='http://127.0.0.1:1242', password='YOUR IPC PASSWORD') as asf:
while True:
await get_log(asf)

loop = asyncio.get_event_loop()
output = loop.run_until_complete(main())
loop.close()

```
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
aiohttp
pyswagger
cchardet
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def find_version(*file_paths):
python_requires='>=3.6, <4',
install_requires=[
'aiohttp',
'pyswagger'
'cchardet',
],
author='deluxghost',
author_email='[email protected]',
Expand Down

0 comments on commit 593b401

Please sign in to comment.