def test_parse_dialogflow_raise_ClientOSError(self):
with OpsDroid() as opsdroid:
opsdroid.config['parsers'] = [
{
'name': 'dialogflow',
'access-token': "test",
"min-score": 0.8}
]
mock_skill = amock.CoroutineMock()
match_dialogflow_action('myaction')(mock_skill)
mock_connector = amock.CoroutineMock()
message = Message("Hello world", "user", "default", mock_connector)
with amock.patch.object(dialogflow, 'call_dialogflow') \
as mocked_call:
mocked_call.side_effect = ClientOSError()
await dialogflow.parse_dialogflow(
opsdroid, message, opsdroid.config['parsers'][0])
self.assertFalse(mock_skill.called)
self.assertTrue(mocked_call.called)
python类ClientOSError()的实例源码
def test_parse_witai_raise_ClientOSError(self):
with OpsDroid() as opsdroid:
opsdroid.config['parsers'] = [
{'name': 'witai', 'access-token': 'test', 'min-score': 0.3}
]
mock_skill = amock.CoroutineMock()
match_witai('get_weather')(mock_skill)
mock_connector = amock.CoroutineMock()
message = Message("how's the weather outside", "user",
"default", mock_connector)
with amock.patch.object(witai, 'call_witai') as mocked_call:
mocked_call.side_effect = ClientOSError()
await witai.parse_witai(opsdroid, message,
opsdroid.config['parsers'][0])
self.assertFalse(mock_skill.called)
self.assertTrue(mocked_call.called)
def test_parse_luisai_raise_ClientOSError(self):
with OpsDroid() as opsdroid:
opsdroid.config['parsers'] = [
{'name': 'luisai',
'appid': 'test',
'appkey': 'test',
'verbose': True,
'min-score': 0.95}
]
mock_skill = amock.CoroutineMock()
match_luisai_intent('Calendar.Add')(mock_skill)
mock_connector = amock.CoroutineMock()
message = Message("schedule meeting", "user", "default",
mock_connector)
with amock.patch.object(luisai, 'call_luisai') as \
mocked_call:
mocked_call.side_effect = ClientOSError()
await luisai.parse_luisai(opsdroid, message,
opsdroid.config['parsers'][0])
self.assertFalse(mock_skill.called)
self.assertTrue(mocked_call.called)
def test_parse_recastai_raise_ClientOSError(self):
with OpsDroid() as opsdroid:
opsdroid.config['parsers'] = [
{
'name': 'recastai',
'access-token': "test",
}
]
mock_skill = amock.CoroutineMock()
match_recastai('greetings')(mock_skill)
mock_connector = amock.CoroutineMock()
message = Message("Hello", "user", "default", mock_connector)
with amock.patch.object(recastai, 'call_recastai') \
as mocked_call:
mocked_call.side_effect = ClientOSError()
await recastai.parse_recastai(
opsdroid, message, opsdroid.config['parsers'][0])
self.assertFalse(mock_skill.called)
self.assertTrue(mocked_call.called)
def longpoll_processor(self):
await self.init_long_polling()
session = aiohttp.ClientSession(loop=self.loop)
while True:
try:
self.longpoll_request = session.get(self.server, params=self.values)
resp = await self.longpoll_request
except aiohttp.ClientOSError:
session = aiohttp.ClientSession(loop=self.loop)
except (asyncio.TimeoutError, aiohttp.ServerDisconnectedError):
self.logger.warning("Long polling server doesn't respond. Changing server")
await self.init_long_polling()
continue
try:
events = json.loads(await resp.text())
except ValueError:
continue
failed = events.get('failed')
if failed:
err_num = int(failed)
if err_num == 1: # 1 - update timestamp
self.values['ts'] = events['ts']
elif err_num in (2, 3): # 2, 3 - new data for long polling
await self.init_long_polling(err_num)
continue
self.values['ts'] = events['ts']
for event in events['updates']:
asyncio.ensure_future(self.process_longpoll_event(event))
def request(self, url, **kwargs):
try:
status, data = await self._request(url, **kwargs)
except ClientOSError as e:
raise StorageError('URL %s: %s' % (url, e)) from e
if self._return_status:
return status, data
if status == 404:
data = None
elif status >= 400:
raise StorageError('URL %s: %s' % (url, status))
return data
def parse_witai(opsdroid, message, config):
"""Parse a message against all witai skills."""
matched_skills = []
if 'access-token' in config:
try:
result = await call_witai(message, config)
except aiohttp.ClientOSError:
_LOGGER.error("No response from wit.ai, check your network.")
return matched_skills
if 'code' in result:
_LOGGER.error("wit.ai error - %s %s", str(result['code']),
str(result['error']))
return matched_skills
elif result['entities'] == {}:
_LOGGER.error("wit.ai error - No intent found. Did you "
"forget to create one?")
return matched_skills
try:
confidence = result['entities']['intent'][0]['confidence']
except KeyError:
confidence = 0.0
if "min-score" in config and confidence < config['min-score']:
_LOGGER.info("wit.ai score lower than min-score")
return matched_skills
if result:
for skill in opsdroid.skills:
if "witai_intent" in skill:
if (skill['witai_intent'] in
[i['value'] for i in
result['entities']['intent']]):
message.witai = result
matched_skills.append({
"score": confidence,
"skill": skill["skill"],
"config": skill["config"],
"message": message
})
return matched_skills
def dispatch(self, request: Request):
service_addr = await self._resolver.resolve(request)
print('service_addr:', service_addr)
# we need the headers as a dict:
headers = CIMultiDict()
for k, v in request.headers:
headers[k.decode()] = v.decode()
# aiohttp will try to do a len on the content if there is
# no content-length header. Since we aren't currently supporting
# streaming incoming, we are going to just pretend that there is
# no data...
if headers.get('Content-Length') is None:
data = None
else:
data = request.content
try:
async with self._session.request(request.method.decode(),
service_addr,
data=data,
headers=headers) as resp:
# TODO: Need to support any other versions?
# TODO: Abstract to response class.
request.transport.write(b'HTTP/1.1 %d %b\r\n' % (resp.status,
resp.reason.encode())) # noqa
# TODO: Figure out how to use raw_headers to bypass en/decode
for k, v in resp.headers.items():
request.transport.write(b'%b: %b\r\n' % (k.encode(),
v.encode()))
request.transport.write(b'\r\n')
while True:
chunk = await resp.content.readany()
if not chunk:
break
request.transport.write(chunk)
request.transport.close()
except ClientOSError:
raise HTTPBadGatewayException('Unable to reach destination, '
'service unreachable.')
def on_command_error(error, ctx):
if isinstance(error, commands.CommandNotFound):
return
if isinstance(error, commands.DisabledCommand):
return
try:
if isinstance(error.original, discord.Forbidden):
return
elif isinstance(error.original, discord.HTTPException) and 'empty message' in str(error.original):
return
elif isinstance(error.original, aiohttp.ClientOSError):
return
except AttributeError:
pass
if isinstance(error, commands.BadArgument):
fmt = "Please provide a valid argument to pass to the command: {}".format(error)
await bot.send_message(ctx.message.channel, fmt)
elif isinstance(error, commands.CheckFailure):
fmt = "You can't tell me what to do!"
await bot.send_message(ctx.message.channel, fmt)
elif isinstance(error, commands.CommandOnCooldown):
m, s = divmod(error.retry_after, 60)
fmt = "This command is on cooldown! Hold your horses! >:c\nTry again in {} minutes and {} seconds" \
.format(round(m), round(s))
await bot.send_message(ctx.message.channel, fmt)
elif isinstance(error, commands.NoPrivateMessage):
fmt = "This command cannot be used in a private message"
await bot.send_message(ctx.message.channel, fmt)
elif isinstance(error, commands.MissingRequiredArgument):
await bot.send_message(ctx.message.channel, error)
else:
now = datetime.datetime.now()
with open("error_log", 'a') as f:
print("In server '{0.message.server}' at {1}\nFull command: `{0.message.content}`".format(ctx, str(now)),
file=f)
try:
traceback.print_tb(error.original.__traceback__, file=f)
print('{0.__class__.__name__}: {0}'.format(error.original), file=f)
except:
traceback.print_tb(error.__traceback__, file=f)
print('{0.__class__.__name__}: {0}'.format(error), file=f)
def start_shard(self, shard_id, future=None):
if self.loop.is_closed():
print(f"Event loop closed, exiting shard#{shard_id}")
if future is None:
print(f"Starting {paint(self.bot_class.__name__, 'cyan')}<{shard_id}>")
else:
try:
result = future.result()
except asyncio.CancelledError: # task was cancelled, it was probably the close_all call
return
except aiohttp.ClientOSError:
if self.shard_connect_failures[shard_id] < 4:
self.shard_connect_failures[shard_id] += 1
print(f"Shard#{shard_id} lost connection, retrying with {paint(self.shard_connect_failures[shard_id], 'red')} failures so far")
else:
print(f"Shard#{shard_id} could not connect after 4 retries")
return
if all(retries == 4 for retries in self.shard_connect_failures.values()):
print(paint("All shards lost connection.", "red"))
sys.exit(1)
except Exception as e:
print(f"Shard#{shard_id} failed to run: [{paint(type(e).__name__, 'b_red')}]: {e}")
else:
print(f"{paint(self.bot_class.__name__, 'cyan')}<{shard_id}>: {result}")
print(f"Attempting resume of shard#{shard_id}")
new_shard = self.bot_class(self, shard_id, *self.args, **self.kwargs)
new_shard.add_cog(Builtin(new_shard))
shard_task = self.loop.create_task(new_shard.start(self.credentials["token"]))
shard_task.add_done_callback(partial(self.start_shard, shard_id)) # oh this is weird
self.shard_tasks[shard_id] = shard_task
self.shards[shard_id] = new_shard
if shard_id not in self.shard_connect_failures:
self.shard_connect_failures[shard_id] = 0
def parse_luisai(opsdroid, message, config):
"""Parse a message against all luisai skills."""
matched_skills = []
if 'appid' in config and 'appkey' in config:
try:
result = await call_luisai(message, config)
except aiohttp.ClientOSError:
_LOGGER.error("No response from luis.ai, check your network.")
return matched_skills
if result:
# if there is an error (eg. 404 error)
# luis.ai responds with a status code
try:
if result["statusCode"] >= 300:
_LOGGER.error("luis.ai error - %s %s",
str(result["statusCode"]), result["message"])
except KeyError:
pass
if "min-score" in config and \
result["topScoringIntent"]["score"] \
< config["min-score"]:
_LOGGER.debug("luis.ai score lower than min-score")
return matched_skills
for skill in opsdroid.skills:
if "luisai_intent" in skill:
try:
intents = [i["intent"] for i in result["intents"]]
except KeyError:
continue
if skill["luisai_intent"] in intents:
message.luisai = result
matched_skills.append({
"score": result["topScoringIntent"]["score"],
"skill": skill["skill"],
"config": skill["config"],
"message": message
})
return matched_skills
def parse_dialogflow(opsdroid, message, config):
"""Parse a message against all Dialogflow skills."""
matched_skills = []
if 'access-token' in config:
try:
result = await call_dialogflow(message, config)
except aiohttp.ClientOSError:
_LOGGER.error("No response from Dialogflow, check your network.")
return matched_skills
if result["status"]["code"] >= 300:
_LOGGER.error("Dialogflow error - %s - %s",
str(result["status"]["code"]),
result["status"]["errorType"])
return matched_skills
if "min-score" in config and \
result["result"]["score"] < config["min-score"]:
_LOGGER.debug("Dialogflow score lower than min-score")
return matched_skills
if result:
for skill in opsdroid.skills:
if "dialogflow_action" in skill or \
"dialogflow_intent" in skill:
if ("action" in result["result"] and
skill["dialogflow_action"] in
result["result"]["action"]) \
or ("intentName" in result["result"] and
skill["dialogflow_intent"] in
result["result"]["intentName"]):
message.dialogflow = result
message.apiai = message.dialogflow
_LOGGER.debug("Matched against skill %s",
skill["config"]["name"])
matched_skills.append({
"score": result["result"]["score"],
"skill": skill["skill"],
"config": skill["config"],
"message": message
})
return matched_skills