can't assign a value to a variable in a #classmethod - python

I have a bit of background in Java and used static variables and methods a lot. I am new to python and learning about using #classmethod as a static method.
Here is code,
import redis
class GetClients:
r = None
#classmethod
def connect_r(cls, host, port, db):
r = redis.StrictRedis(host=host, port=port, db=db)
#classmethod
def get_clients(cls, clients_key):
return r.smembers(clients_key)
My code first create a variable r and then inside a classmethod it assigns it to a redis connection, r = redis.StrictRedis(host=host, port=port, db=db)
In the next method get_clients, I am using the value of r to invoke a function on it., but I keep getting the following error
NameError: name 'r' is not defined
here is how i am using the class,
clients = GetClients()
clients.connect_r("localhost", 6379, 0)
allc = clients.get_clients("clients")
can someone please explain why I cannot access r in the 2nd method?

The problem is r in both class methods, you should replace r with cls.r.
like this:
import redis
class GetClients:
r = None
#classmethod
def connect_r(cls, host, port, db):
cls.r = redis.StrictRedis(host=host, port=port, db=db)
#classmethod
def get_clients(cls, clients_key):
return cls.r.smembers(clients_key)
But I think that your way of implementing these methods are a little bit wrong, you should not use class methods for this demands.
can someone please explain why I cannot access` in the 2nd method?
I should say that you can not even access r in connect_r too. that r is another variable with a different scop and if you want to see what will happen just change r to cls.r in get_clients, you will see that this method will returns None and it seems that connect_r method is not setting the actual r, for accessing those variables in class methods you should use cls.
also see the difference between cls and self here.

Related

How to use dependencies with yield in FastApi

I am using FastApi and I would like to know if I am using the dependencies correctly.
First, I have a function that yields the database session.
class ContextManager:
def __init__(self):
self.db = DBSession()
def __enter__(self):
return self.db
def __exit__(self):
self.db.close()
def get_db():
with ContextManager() as db:
yield db
I would like to use that function in another function:
def validate(db=Depends(get_db)):
is_valid = verify(db)
if not is is_valid:
raise HTTPException(status_code=400)
yield db
Finally, I would like to use the last functions as a dependency on the routes:
#router.get('/')
def get_data(db=Depends(validate)):
data = db.query(...)
return data
I am using this code and it seems to work, but I would like to know if it is the most appropiate way to use dependencies. Especially, I am not sure if I have to use 'yield db' inside the function validate or it would be better to use return. I would appreciate your help. Thanks a lot

How to use a var in multiple methods in python

I have a few files in my code that speak to the database
This might look something like this:
def addUser():
# some code
def verifyUser():
# some code
def addStuffToDB():
# some code
In all of the above I need to use a variable - let's call it db - that holds a reference to the database (as opposed to redefining it in every function)
How would I do this? How can I have functions in one or more files that all make use of a variable (in this case db)
Thanks
If you have all this functions inside the same file, it is enough to just define variable db outside any function (this will make it global). Now all functions will be able to see db variable. But if you change db inside a function it will not change outside the function.
If you have this variable in another file you can simple import it like
from file_name import db
As #ddejohn said, you should wrap your functions in a class, so the variable self.db would have a class scope.
class DB():
def __init__(self) -> None:
self.db = "DB_connection or something..."
def addUser(self):
#Some code, acess db variable with self.db
def verifyUser(self):
#Some code, acess db variable with self.db
def addStuffToDB(self):
#Some code, acess db variable with self.db
MyDB = DB()
MyDB.addUser()
Thanks for asking the question.
You need to pass db as argument while calling the funcs like the following
db = "some referenec"
def addUser(database):
## now you can use db
# some code
def verifyUser(database):
# some code
## now you can use db
def addStuffToDB(database):
# some code
## now you can use db
## while calling each func pass db as argument like this
addUser(db)
verifyUser(db)
addStuffToDB(db)
add a db paramenter to yout funcs:
controller.py:
def addUser(db): # some code
obj.add(db)
def verifyUser(db): # some code
obj.verify(db)
def addStuffToDB(db): # some code
obj.add_stuff(db)
Then, you can use as follows:
view.py
import db
from controller import addUser
addUser(db)

Accesing class variable from another script using python

I am facing weird error when I try to access self.cursor_dat' from class in different script. It says:ImportError: cannot import name query_selection_class`. The error also occur without trying to access the variable. There is just something wrong with the import command.
here is the file1.py where I create the variable:
class connection_settings_class(QtGui.QMainWindow,Ui_main_connection_settings_window):
def __init__(self):
self.create_connection_window()
self.host = 'localhost'
self.port = '3307'
self.user = 'root'
self.password = ''
self.database = 'rtr'
def connection(self):
""" connect to the database and create cursor that will be used to exetute MySQL queries """
try:
self.cnxn = pyodbc.connect(driver = '{MySQL ODBC 5.3 ANSI Driver}', # ANSI or Unicode
host = self.host,
port = self.port,
user = self.user,
password = self.password,
database = self.database)
except:
print('Connection FAIL')
**self.cursor_dat** = self.cnxn.cursor()
**self.cursor_dat**.execute("""SELECT * FROM test_db.attempt;""")
row = **self.cursor_dat**.fetchone()
if row:
print("Succesfully connected to the database.")
print row
self.status_label.setText("Connected")
else:
print("Connection FAIL")
self.status_label.setText("Disconnected")
def create_connection_window(self):
...rest of the code
...and here is file2
import file1 -> I also tried from file1 import connection_settings_class
class plausible_implausible_class(QtGui.QMainWindow,Ui_plausible_implausible_win):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
self.show()
sc = MyStaticMplCanvas(self.centralwidget, width=500, height=400, dpi=100)
self.verticalLayout_3.addWidget(sc)
**a = file1.connection_settings_class.cursor_dat**
I might be making a really dumb mistake looking at your sample, but what I see is this:
self.cursor_dat= self.cnxn.cursor()
is defined in the connection_settings_class.connection() method. You never call connection(), so that property never gets created.
Also I noticed that you're calling the class statically, rather than creating an instance of the class but you've created no static properties, they're all created on __init__. You may want to create an instance of your class, which then defines the cursor_dat to be None initially.
If you want connection sharing you can set up a pool of connections and still create individual instances.
Ok, there is not problem with the path because all the scripts that #tdelaney mentioned were positive. The result of for cycle is '/Users/BauchMAC/PycharmProjects/py_GUI/Database_GUI' --> True. And the working directory which I got using os.getcwd() is same.
I also tried to create two new scripts and everything worked. So the problem is that I don't understand to "importing rules" in python because this is the source of the problem.
So there is obviously problem with crossing of imports. And the way to solve it is by passing the value as the parameter.
Below you can see how I wanted to do it and the reason for the error:
file1:
from try4 import ClassB
class ClassA():
def __init__(self):
self.cursor_dat = 1
self.query_selection_win = ClassB()
object1 = ClassA()
file 2:
from try3 import ClassA <-- source of the probles
class ClassB():
def __init__(self, cursor_dat):
print(ClassA.cursor_dat)
And here is how it should be (at least it works, I am not sure if it is the best way how to do it, I am still newbie)
file 1:
from try4 import ClassB
class ClassA():
def __init__(self):
self.cursor_dat = 1
self.query_selection_win = ClassB(self.cursor_dat)
object1 = ClassA()
file 2:
class ClassB():
def __init__(self, cursor_dat):
print(cursor_dat)
I hope it will be helpful to some newbie like me :)

Can't connect to MongoDB database and collection through class variables

Just as a preface, I understand that there are easier ways to accomplish much of what i'm trying to do, and the following question is for purposes of learning how to build classes and instantiate a database connection within that class.
I'm building a class that right now just takes in two variables; the name of MongoDB database, and the collection name from that database. I am trying to instantiate the connection of this database and the collection in the init function of this class. The problem I am having is that the init function is connecting to the database of the actual name of the variable instead of the variable's actual assignment. More specifically, if I instantiate,
>>>salesChar = MongoDumps("sales","char")
and then I call,
>>>salesChar.db.name
it will instead connect to the "dBase" (the name of the variable) database instead of the "salesChar" (the assignment of the dBase variable) database. Please view code below,
import pymongo
from pymongo import MongoClient
class MongoDumps():
"""Data Dumping into MongoDB"""
def __init__(self, dBase, dumpCollection):
self.dBase = dBase
self.dumpCollection = dumpCollection
client = MongoClient()
self.db = client.dBase
self.collection = self.db.dumpCollection
I've tried a combination of strategies and none seem to work with a similar result in each one. Are there certain limitations to using assignments in a class? Thanks for your help!
Use getattr to get property by string. As documentation says, getattr(x, 'foobar') is equivalent to x.foobar. Your code should look like:
class MongoDumps():
def __init__(self, dBase, dumpCollection):
self.dBase = dBase
self.dumpCollection = dumpCollection
client = MongoClient()
self.db = getattr(client, dBase)
self.collection = getattr(self.db, dumpCollection)
Then you can use this class to get collection by name:
salesChar = MongoDumps("sales", "char")
first = salesChar.collection.find_one()

Mocking chained calls in Python

I am trying to test the following class using unittest and the mock library:
class Connection(object):
def __init__(self, cookie):
self.connect = None
self.session = Session()
self.session.load(cookie)
# do some stuff with self.session
self.some_info = self.session.data['the_info']
How could I test if when I create an instance of Connection, depending on the return of the Session instance, I assert if self.some_info is with the value I am expecting?
I wish to use the mock library. In its documentation I have an example of mocking chained calls (http://www.voidspace.org.uk/python/mock/examples.html#mocking-chained-calls), but it isn't very clear of how I can adapt it to my problem.
The Session.load(cookie) method sets some attributes in the Session instance. I would like to set this values fixed for my tests for every value of cookie.
Assume Connection is located in module package.module.connection
The following code should be how you would test your session:
import mock
class TestConnection(unittest.TestCase):
#mock.patch('package.module.connection.Session')
def test_some_info_on_session_is_set(self, fake_session):
fake_session.data = {'the_info': 'blahblah'}
cookie = Cookie()
connection = Connection(cookie)
self.assertEqual(connection.some_info, 'blahblah')
fake_session.load.assert_called_once_with(cookie)

Categories