How to iterate a variable in fabric ssh? - python

For example:
global count
count += 1
#task
def install(hosts, local_swift_config):
env.use_ssh_config = True
env.hosts = set_hosts(hosts)
execute(place_count)
def place_count():
sudo('echo {} > /home/user/some_count'.format(count))
count += 1
It doesn't have to be a global, what is the preferred way to do this with fabric?

count = 0
#task
def install(hosts, local_swift_config):
env.use_ssh_config = True
env.hosts = set_hosts(hosts)
execute(place_count)
def place_count():
sudo('echo {} > /home/user/some_count'.format(count))
global count
count += 1
I've had this work for simple functions in fabric. Your problem is with python globals, not fabric.
See this thread for more information on globals: Stacokverflow Python Globals

I decided not to use global:
def counter():
env.count += 1
if env.count == 2:
env.count += 4
#task
def install(hosts):
env.count = 0
execute(counter)
print(env.count)
execute(counter)
print(env.count)
execute(counter)
print(env.count)
Ouput:
1
6
7
Done.

Related

manipulating variable value in unit test case python

I am having this method below:
def pagination_logic(self, topic_name):
"""Pagination logic to fetch the complete data.
:param topic_name:str, kafka topic name.
"""
while self.next_page_cursor:
self.fetch_response_from_api()
records = self.extract_records()
self.publish_records(records, topic_name)
if not self.flag:
break
self.extract_next_page_cursor()
self.page += 1
else:
logger.info("Finished fetching data")
I need to write a unit test method. Below is my unit test method
def test_pagination_logic(self):
"""Test for pagination logic."""
allow(self.slack).fetch_response_from_api.and_return(None)
allow(self.slack).extract_records.and_return(RESPONSE.get('entries'))
allow(self.slack).publish_records.and_return(None)
allow(self.slack).extract_next_page_cursor.and_return(None)
self.slack.next_page_cursor = 'abc'
self.slack.flag = 0
result = self.slack.pagination_logic('topic_name')
assert result is None
I know that I can achieve 100% coverage for this by setting the value of self.flag as 1 for the first iteration and 0 for the second iteration.
But how can I achieve that?.
Try doing like this. This is a bit hacky but I think this might work:
class Helper:
def __init__(self):
self.s_obj = None
def update_flag():
if self.s_obj.flag == 1:
self.s_obj.flag = 0
class YourTestClass:
def test_pagination_logic(self):
"""Test for pagination logic."""
...
h_obj = Helper()
h_obj.s_obj = self.slack
allow(self.slack).extract_next_page_cursor.and_return_result_of(h_obj.update_flag)
self.slack.flag = 1
result = self.slack.pagination_logic('topic_name')
....

How to update a global variable across multiple functions in Python

I have the following code:
counter = 0
def function_1():
func_2(counter)
def func_2(counter):
func_3(counter)
def func_3(counter):
counter += 1
My goal is to keep track of counter incrementation in func_3() in all other functions.
I tried to make counter global
counter = 0
def function_1():
global counter
func_2(counter)
def func_2(counter):
func_3(counter)
def func_3(counter):
counter += 1
but it does not work, the counter incrementation is just local to func_3()
Any hints?
I tried to find an easy to understand explanation for you, but they all seemed to complicated.
The reason that you are seeing counter as a local variable inside your functions is because you are defining it in the function definition: def func_2(counter):.
To use the global counter inside a function you need to do it like this:
counter = 0
def function_1():
func_2()
def func_2():
func_3()
def func_3():
global counter
counter += 1
You can use globals().update(locals()), example:
counter = 0
def function_1():
func_2()
def func_2():
func_3()
def func_3():
counter += 1
globals().update(locals())
or use global method
counter = 0
def function_1():
func_2()
def func_2():
func_3()
def func_3():
global counter
counter += 1

Pythonic way to update multiple class variables in a loop?

I would like to update class variables with similar names in a loop:
I have the following code:
class Table:
def __init__(self):
pass
acc_counter = 0
acc0 = 0
acc1 = 0
acc2 = 0
acc3 = 0
acc4 = 0
I could update each value manually:
Table.acc0 = 0
Table.acc1 = 1
Table.acc2 = 2
Table.acc3 = 3
Table.acc4 = 4
However, I'm wondering if I could do it in a loop, something like that:
for i in range(5):
print(getattr(Table, f"acc{i}"))
#getattr(Table, f"acc{i}") = i
If the last line of the code is uncommented it returns: "SyntaxError: can't assign to function call"
You can use the setattr function:
for i in range(5):
setattr(Table, f"acc{i}", i)
Use setattr to set the object's attribute value
for i in range(5):
print(getattr(Table, f"acc{i}"))
setattr(Table, f"acc{i}", i)

How can I access values from the 'self' dictionary through iteration?

I don't know how to effectively word my question, but I'll try my best. I want to be able to use a 'for' statement to iterate through a dictionary and access previously-made 'self' items. Like I said, hard to word the question.
I have found that I can use exec() to do it, but I had been told not to use exec() unless absolutely necessary. Also, I realize what this example does is technically useless, but it's a very simplified version of what I need.
global counter
counter = 0
class GUI:
def __init__(self):
self.stuff = ["foo","bar","fooest","barest"]
for i in self.stuff:
self.process(i)
self.printAll()
def process(self,i):
global counter
counter += 1
self.__dict__.update({"ex{}".format(counter):i})
def printAll(self):
global counter
while counter > 0:
exec("print(self.ex{})".format(counter))
counter -= 1
GUI()
This does work; printAll(self) does print self.ex1 thru ex4. Is there a way to do it without exec()?. Please help!
global counter
counter = 0
class GUI:
def __init__(self):
self.stuff = ["foo","bar","fooest","barest"]
for i in self.stuff:
self.process(i)
self.printAll()
def process(self,i):
global counter
counter += 1
self.__dict__.update({"ex{}".format(counter):i})
def printAll(self):
global counter
while counter > 0:
print(eval("self.ex{}".format(counter)))
counter -= 1
GUI()
I hope this is suitable in your case

How to call variables from other files python with classes?

Hi all I would like to know how to call variables (which are inside classes) from other python files. I am aware of the bellow method of doing this however it will not work if the class is called from the original file.
from (insert_file_name_hear) import *
This a similar sample to what I'm working with:
functions.py
num = 0
num2 = 0
class Test():
def alt_num(self):
global alt_num
alt = 55
def change(self):
global num, num2
num += alt_num
num2 = num
def print_num():
global num2
print(num2)
def work():
Test.alt_num(Test)
Test.change(Test)
print_num()
print.py
from functions import *
work()
def printing():
print(num2)
printing()
When I run print.py it will accuratly print in the functions.py file however it will print 0 in the print.py file. Note: Both files are in the same folder and I am running this in Python 3.
Thanks
Instead of using Globals you can use class variables with a little bit of effort
functions.py
class Test():
num = 0
num2 = 0
alt = 0
#classmethod
def alt_num(cls):
cls.alt = 55
#classmethod
def change(cls):
cls.num += cls.alt
cls.num2 = cls.num
def print_num():
print(Test.num2)
def work():
Test.alt_num()
Test.change()
print_num()
Test.change()
print_num()
Test.change()
print_num()
return Test.num2
print.py
from functions import *
work()
def printing():
print(Test.num2)
printing()
Note: the output of the above is
55
110
165
165
The first three come from work(), the last from printing()
First - alt and alt_num are not defined
Second - You need to return the variable through a function to use it elsewhere
Below is how you can do this
functions.py
alt = 0
num = 0
num2 = 0
class Test():
def alt_num(self):
global alt
alt = 55
def change(self):
global num, num2
num += alt
num2 = num
def print_num():
global num2
def work():
Test.alt_num(Test)
Test.change(Test)
print_num()
return num2
print.py
from functions import *
def printing():
print(work())
printing()
In functions.py you declare num2 = 0, the rest of the manipulation of num2 is made inside functions that do not return the new value.
The function print_num() actually prints the new value of num2, this is where 55 comes from in the output.
In print.py you are printing the num2 that is declared on line 2 of functions.py
If you are only interested in num2 after the value has been updated you could skip the printing in functions.py, instead return the value and print it from print.py.
It could look something like this.
functions.py
num = 0
class Test():
def alt_num():
global alt
alt = 55
def change():
global num
global num2
num += alt
num2 = num
def work():
Test.alt_num()
Test.change()
return(num2)
print.py
from functions import *
def printing():
print(work())
printing()

Categories

Resources