brownie - How do I handle exceptions? - python

I've been watching a brownie tutorial video by Patrick (fantastic lad). Still, I seem to be getting an error when running a particular function, but the rest of the functions run perfectly. I don't know where I went wrong.
I've attached the code snippet and the error message
def test_can_pick_winner_correctly():
# Arrange
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({"from": account})
lottery.enter({"from": account, "value": lottery.getEntranceFee()})
lottery.enter({"from": get_account(index=1), "value": lottery.getEntranceFee()})
lottery.enter({"from": get_account(index=2), "value": lottery.getEntranceFee()})
fund_with_link(lottery)
starting_balance_of_account = account.balance()
balance_of_lottery = lottery.balance()
transaction = lottery.endLottery({"from": account})
> request_id = transaction.events["RequestedRandomness"]["requestId"]
E brownie.exceptions.EventLookupError: Event 'RequestedRandomness' did not fire.
tests/test_lottery_uint.py:78: EventLookupError
------------------------------------------------------- Captured stdout call --------------------------------------------------------
Deployed lottery!
Fund contract!
====================================================== short test summary info ======================================================
FAILED tests/test_lottery_uint.py::test_can_pick_winner_correctly - brownie.exceptions.EventLookupError: Event 'RequestedRandomnes...
This the error message, and below is the code snippet that includes the imports and the particular function
from scripts.helpful_scripts import (
LOCAL_BLOCKCHAIN_ENVIRONMENTS,
get_account,
fund_with_link,
get_contract,
)
from brownie import Lottery, accounts, config, network, exceptions
from scripts.deploy_lottery import deploy_lottery
from web3 import Web3
import pytest
These are the imports and the particular function is below
def test_can_pick_winner_correctly():
# Arrange
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({"from": account})
lottery.enter({"from": account, "value": lottery.getEntranceFee()})
lottery.enter({"from": get_account(index=1), "value": lottery.getEntranceFee()})
lottery.enter({"from": get_account(index=2), "value": lottery.getEntranceFee()})
fund_with_link(lottery)
starting_balance_of_account = account.balance()
balance_of_lottery = lottery.balance()
transaction = lottery.endLottery({"from": account})
request_id = transaction.events["RequestedRandomness"]["requestId"]
STATIC_RNG = 777
get_contract("vrf_coordinator").callBackWithRandomness(
request_id, STATIC_RNG, lottery.address, {"from": account}
)
# 777 % 3 = 0
assert lottery.recentWinner() == account
assert lottery.balance() == 0
assert account.balance() == starting_balance_of_account + balance_of_lottery'

Are you sure that you are emitting that event from
Share the code from
Lottery.sol: endLottery method? As After copy pasting the test method you have provided it passed successfully.

Related

Pypresence not closing connection

This is the code I'm using to turn the pypresence on:
from pypresence import Presence
import time
start = int(time.time())
client_id = "XXXXXXXXXXXXXXXX"
RPC = Presence(client_id, pipe=0, loop=None, handler=None)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "All Systems Operational.",
large_image = "xxx_logo_rpc_v2",
large_text = "exe is running!",
small_image = "xx_green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [{"label": "🌐XX 🌐", "url": "https://xx/"}, {"label": "xxxx", "url": "https://xxxx8"}]
)
time.sleep(60)
This is the code I'm trying to use to turn it off:
from pypresence import Presence
import os
client_id = "XXXXXXXXXXXXXX"
RPC = Presence(client_id, pipe=0, loop=None, handler=None)
RPC.clear(pid=os.getpid())
RPC.close()
The problem is that it shows me this error:
File "C:\Users\Foxii\AppData\Local\Programs\Python\Python310\lib\site- packages\pypresence\baseclient.py",
line 96, in send_data assert self.sock_writer is not None, "You must connect your client before sending events!" AssertionError: You must connect your client before sending events!
Well, the client seems to be connected when I run it with my custom Tkinter GUI but when I try to run the code to close it, it shows me that error.

Python nornir unittest mocking how to?

I'm using the nornir (3.3.0) automation framework with Python 3.8. I'd like to mock the SSH access to the devices in order to do testing without having some real or virtual network equipment online. How would I use patch or Mock/MagicMock from unittest.mock to mock netmiko_send_command (ssh interaction with device)?
I have the following nornir task function:
# dbb_automation/tasks.py
from nornir.core.task import Task, Result
from nornir_netmiko.tasks import netmiko_send_command
def get_interfaces_with_ip(task: Task):
log.debug(f"{task.name}: Getting result on host {task.host}")
result: MultiResult = task.run(name="show ip int br | e unass", task=netmiko_send_command,
command_string="show ip int br | e unass")
content_str = result[0].result
task.run(
task=write_file,
filename=f"outputs/{task.host}-{purpose}.{ending}",
content=content_str
)
return Result(
host=task.host,
result=f"{task.host.name} got ip result"
)
and the following test case (work in progress):
# tests/test_tasks.py
from dbb_automation.tasks import get_interfaces_with_ip
from nornir import InitNornir
from nornir.core.filter import F
from tests.settings import *
def test_get_interfaces_with_ip():
# [x] init nornir with fake host
# [ ] patch/mock netmiko_send_command
# [ ] check file contents with patched return string of netmiko_send_command
nr = InitNornir(
core={
"raise_on_error": True
},
runner={
"plugin": "threaded",
"options": {
"num_workers": 1,
}
},
inventory={
"plugin": "SimpleInventory",
"options": {
"host_file": DNAC_HOSTS_YAML,
"group_file": DNAC_GROUPS_YAML,
"defaults_file": DNAC_DEFAULT_YAML
}
},
logging={
"log_file": "logs/nornir.log"
}
)
result = nr.filter(F(has_parent_group="Borders")).run(name="get_interfaces_with_ip", task=get_interfaces_with_ip)
# todo: test code
assert False
Regards,
Gérard
I think I found the solution. Key was to patch to where the imported function is used not to where it is defined and to set the return value on the mock object.
#patch("dbb_automation.tasks.netmiko_send_command")
def test_get_interfaces_with_ip(mock_netmiko_send_command, nr):
...
mock_netmiko_send_command.return_value = """Interface IP-Address OK? Method Status Protocol
GigabitEthernet22 10.1.54.146 YES TFTP up up
Loopback0 10.150.32.2 YES other up up
Port-channel1.2 10.150.33.65 YES manual up up
...
"""
import pytest
import os
import shutil
from unittest.mock import patch
from dbb_automation.tasks import get_interfaces_with_ip
from nornir import InitNornir
from nornir.core.filter import F
from tests.settings import *
#pytest.fixture()
def nr():
nr = InitNornir(
core={
"raise_on_error": True
},
runner={
"plugin": "threaded",
"options": {
"num_workers": 1,
}
},
inventory={
"plugin": "SimpleInventory",
"options": {
"host_file": DNAC_HOSTS_YAML,
"group_file": DNAC_GROUPS_YAML,
"defaults_file": DNAC_DEFAULT_YAML
}
},
logging={
"log_file": "logs/nornir.log"
}
)
return nr
#patch("dbb_automation.tasks.netmiko_send_command")
def test_get_interfaces_with_ip(mock_netmiko_send_command, nr):
output_folder_name = "outputs"
shutil.rmtree(output_folder_name)
os.mkdir(output_folder_name)
mock_netmiko_send_command.return_value = """Interface IP-Address OK? Method Status Protocol
GigabitEthernet22 10.1.54.146 YES TFTP up up
Loopback0 10.150.32.2 YES other up up
Port-channel1.2 10.150.33.65 YES manual up up
"""
nr.filter(F(has_parent_group="Borders")).run(name="get_interfaces_with_ip", task=get_interfaces_with_ip)
# test code
count = 0
files_found = None
for root_dir, cur_dir, files in os.walk(output_folder_name):
count += len(files)
assert files_found is None # make sure there are no subdirectories
files_found = files
assert count == 4 # we expect a file for each host
for file_name in files_found:
with open(f"{output_folder_name}/{file_name}") as f:
assert f.read() == mock_netmiko_send_command.return_value

Discord Pypresence crashing custom application after pressing connect button

This is how the application looks like: [1]: https://i.stack.imgur.com/HUaix.png
[2]: https://i.stack.imgur.com/CYWdS.png
The second [2] image shows how the application should look after pressing the "Connect" button. However, after pressing the button it looks the same (image [1]), although the Discord rich presence starts running.
def rpcstart():
os.system('start-rpc-script.py')
global rpc_on
if rpc_on:
connectbutton.config(image=rpcconnectedimage, state='disabled')
disconnectbutton.config(image=rpcdisconnectimage, state='normal')
else:
connectbutton.config(image=rpcconnectimage)
menubar.entryconfig(1,label="Status: Connected")
This is the part of my script that starts the Discord rich presence. There are no errors or anything similar. It just makes the application unresponsive. Is there any fix for that? Here's the pypresence script that I use:
from pypresence import Presence
import time
start = int(time.time())
client_id = "XXXXXX"
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}]
)
time.sleep(60)
Try running your RPC code in a separate thread
from threading import Thread
def _rpc_connect(client_id): # this will be your 'target' function, run in its own thread
start = int(time.time())
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [
{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}
],
)
time.sleep(60)
def run_rpc(client_id)
t_rpc = Threading(
target=_rpc_connect,
args=(client_id,),
daemon=True,
)
t_rpc.start() # start the thread
To run the RPC thread, call the run_rpc function as usual
run_rpc(client_id='XXXXXX')

how to access these mocks in unittest and pytest

I'm trying to test this function "start_dojot_messenger", which has some objects and methods in it, and I need to test and verify that they were called with those specific parameters.
For example we have messenger.create_channel("dojot.notifications", "r"), and I need to test if it is starting with these parameters.
follow image of the method
def start_dojot_messenger(config, persister, dojot_persist_notifications_only):
messenger = Messenger("Persister", config)
messenger.init()
# Persister Only Notification
messenger.create_channel("dojot.notifications", "r")
messenger.on(config.dojot['subjects']['tenancy'],
"message", persister.handle_new_tenant)
messenger.on("dojot.notifications", "message",
persister.handle_notification)
LOGGER.info('Listen to notification events')
if str2_bool(dojot_persist_notifications_only) != True:
LOGGER.info("Listen to devices events")
# TODO: add notifications to config on dojot-module-python
messenger.create_channel(config.dojot['subjects']['devices'], "r")
messenger.create_channel(config.dojot['subjects']['device_data'], "r")
messenger.on(config.dojot['subjects']['devices'],
"message", persister.handle_event_devices)
messenger.on(config.dojot['subjects']['device_data'],
"message", persister.handle_event_data)
in my tests I'm doing it that way here.
#patch.object(Persister, 'create_indexes')
#patch.object(Config, 'load_defaults')
#patch('history.subscriber.persister.Messenger')
#patch.object(Messenger, 'create_channel', return_value=None)
#patch.object(Messenger, 'on', return_value=None)
def test_persist_only_notifications(mock_create_channel, mock_on, mock_messenger, mock_config, create_indexes):
from history.subscriber.persister import start_dojot_messenger
from history import conf
p = Persister()
p.create_indexes_for_notifications('admin')
mock_config.dojot = {
"management": {
"user": "dojot-management",
"tenant": "dojot-management"
},
"subjects": {
"tenancy": "dojot.tenancy",
"devices": "dojot.device-manager.device",
"device_data": "device-data"
}
}
# test persist only boolean valued notifications
start_dojot_messenger(mock_config, p, True)
mock_messenger.assert_called()
assert mock_messenger.call_count == 1
the first test to check if the Messenger class has been initialized I can do it using the mock: mock_messenger.assert_called()
but the others I can't access.
I figured it could be something like this
mock_messenger.mock_create_channel.assert_called

use ansible_facts in module code

I am trying to create my own ansible module (which will update cmdb) and i am looking how to use ansible_facts in module code ?
example of my module script is :
#!/usr/bin/python
from ansible.module_utils.basic import *
import json, ast
from servicenow import ServiceNow
from servicenow import Connection
def __get_server_info(table,server_name="", sys_id=""):
if sys_id == "":
return table.fetch_one({'name': server_name})
if server_name == "":
return table.fetch_one({'sys_id': sys_id})
def __update_cmdb_hwinfo(table, sys_id, server_name=""):
return table.update({'sys_id': sys_id,{'hw_ram': 'Here for example i want to put ansible_facts about server ram size'})
def main():
fields = {
"snow_instance": {"required": True, "type": "str"},
"snow_username": {"required": True, "type": "str"},
"snow_password": {"required": True, "type": "str"},
"server_name": {"required": True, "type": "str" },
"api_type": {"default": "JSONv2", "type": "str"},
}
module = AnsibleModule(argument_spec=fields)
snow_connection = Connection.Auth(username=module.params['snow_username'], password=module.params['snow_password'], instance=module.params['snow_instance'], api=module.params['api_typ
e'])
server = ServiceNow.Base(snow_connection)
server.__table__ = 'cmdb_ci_server_list.do'
machine = __get_server_info(server, )
## Define connection object to ServiceNow instance
module.exit_json(changed=False, meta=module.params, msg=machine)
if __name__ == '__main__':
main()
What variable i should use to call ansible_facts in module script? (And is it even possible? ).
I doubt this is possible from inside module itself, because they are executed in the context of remote machine with predefined parameters.
But you can wrap your module with action plugin (that is executed in local context), collect required data from available variables and pass them as parameters to your module.
Like this (./action_plugins/a_test.py):
from ansible.plugins.action import ActionBase
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
result = super(ActionModule, self).run(tmp, task_vars)
module_args = self._task.args.copy()
module_args['mem_size'] = self._templar._available_variables.get('ansible_memtotal_mb')
return self._execute_module(module_args=module_args, task_vars=task_vars, tmp=tmp)
In this case if your module expect mem_size parameter it will be set to ansible_memtotal_mb's value with action plugin.
Module example (./library/a_test.py):
#!/usr/bin/python
def main():
module = AnsibleModule(
argument_spec = dict(
mem_size=dict(required=False, default=None),
),
supports_check_mode = False
)
module.exit_json(changed=False, mem_size=module.params['mem_size'])
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
main()
Test playbook:
---
- hosts: all
tasks:
- a_test:

Categories