How to use a var in multiple methods in python - 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)

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

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

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.

Can't mock the class method in python

I have a class that I try to mock in tests. The class is located in server/cache.py and looks like:
class Storage(object):
def __init__(self, host, port):
# set up connection to a storage engine
def store_element(self, element, num_of_seconds):
# store something
def remove_element(self, element):
# remove something
This class is used in server/app.py similar to this one:
import cache
STORAGE = cache.Storage('host', 'port')
STORAGE.store_element(1, 5)
Now the problem arise when I try to mock it in the tests:
import unittest, mock
import server.app as application
class SomeTest(unittest.TestCase):
# part1
def setUp(self):
# part2
self.app = application.app.test_client()
This clearly does not work during the test, if I can't connect to a storage. So I have to mock it somehow by writing things in 'part1, part2'.
I tried to achieve it with
#mock.patch('server.app.cache') # part 1
mock.side_effect = ... # hoping to overwriting the init function to do nothing
But it still tries to connect to a real host. So how can I mock a full class here correctly? P.S. I reviewed many many questions which look similar to me, but in vain.

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()

How to expose variable in Python module?

What is the best way to expose a variable from a module?
import otherDBInterface as odbi
def create(host):
global connection
global cursor
connection = odbi.connect(host)
cursor = connection.cursor()
...
I want to expose the cursor variable in the module so I can do something like mydb.cursor.execute("select * from foo;"). I thought using the global keyword would do this but no such luck. cursor is an object so I am not sure how I would declare it so that it would be exposed.
You can wrap your connection information in a class
class Database:
def __init__(self, **kwargs):
if kwargs.get("connection") is not None:
self.connection = kwargs["connection"]
elif kwargs.get("host") is not None:
self.connection = odbi.connect(host)
self.cursor = self.connection.cursor()
mydb = Database(host="localhost")
results = mydb.cursor.execute("select * from foo")
#or use it with a connection
mydb = Database(connection="localhost")
results = mydb.cursor.execute("select * from foo")
Any variable created on a module level is "exposed" by default.
Hence, a module like this will have three exposed variables:
configpath = '$HOME/.config'
class Configuration(object):
def __init__(self, configpath):
self.configfile = open(configpath, 'rb')
config = Configuration(configpath)
The variables are configpath, Configuration and config. All of these are importable from other modules. You can also access configs configfile as config.configfile.
You can also have configfile accessible globally this way:
configpath = '$HOME/.config'
configfile = None
class Configuration(object):
def __init__(self, configpath):
global configfile
configfile = open(configpath, 'rb')
config = Configuration(configpath)
But there are various tricky problems with this, as if you get a handle on configfile from another module and it then gets replaced from within Configuration your original handle will not change. Therefore this only works with mutable objects.
In the above example that means that using configfile as a global in this way will not be very useful. However, using config like that could work well.

Categories