Inherited Methods How do I make super methods available? - python

I have a class (which works [or appears to]) to run an sql query. Code is below. If I inherit from object and do not use super, it works fine.
I am learning about inserting methods from super classes and so I thought that I would make my class header look like this
class database_connector(Connection)
and incorporate a super call in init like this
super().__init__()
However, I get
TypeError: function() argument 1 must be code, not str
I tried
super(database_connector, self).__init__()
after reading some other stuff in StackOverFlow but I now still get
TypeError: function() argument 1 must be code, not str
I am anticipating that this work will allow me to call more methods from pymysql.Connection.
Here is my class
from pymysql import Connection
# set up default values for database connector
class database_connector(Connection):
def __init__(self, host=None, db=None, user=None, passwd=None):
super(database_connector, self).__init__()
if host is None:
self.host = "mysql_host_ip"
else:
self.host = host
if db is None:
self.db = "fred_db"
else:
self.db = db
if user is None:
self.user = "fred"
else:
self.user = user
if passwd is None:
self.passwd = "fredspasswd"
else:
self.passwd = passwd
self.this_database = (Connection(host=self.host,
user=self.user,
passwd=self.passwd,
db=self.db))
self.cur = self.this_database.cursor()
def my_sql_run_this_sql(self, sql_to_run=None):
if sql_to_run is None:
data = self.cur.execute("SELECT * FROM person")
else:
data = self.cur.execute(sql_to_run)
data = []
for row in self.cur.fetchall():
data.append(row)
self.this_database.close()
return data

Related

I want to specify the class (type) of the parameter

class PostgreSql():
def __init__(self):
pass
class User():
def __init__(self):
pass
def set_dsn(self, connects_database: bool):
self.dsn = "host={host} user={user} password={password} port={port}".format(
host=self.host,
user=self.user,
password=self.password,
port=self.port,
)
if connects_database==True:
self.dsn = "{dsn} {database}".format(
dsn=self.dsn,
database=self.database
)
def set_host(self, host: str):
self.host = host
def set_user(self, user: str, password: str):
self.user = user
self.password = password
def set_port(self, port: str):
self.port = port
def set_database(self, database: str):
self.database = database
class Session():
def __init__(self):
pass
def connect(self, dsn: str):
self.con = psycopg2.connect(dsn=dsn)
self.cur = self.con.cursor()
def create_database(self, name: str):
query = SQL("CREATE DATABASE {name}").format(name=Identifier(name))
try:
self.cur.execute(query=query)
except DuplicateDatabase:
print("{name} Database Already Created.".format(name=name))
else:
print("{name} Database Create.".format(name=name))
def create_table(self, name: str, coulmn: str):
"""This function is create new table in database of instance connection.
Args:
name : Name of the table to be created.
coulmn : Column in the table to be created.
Format is "(name data_type condition, name2 data_type2 condition2...)".
"""
self.cur.execute(
query=SQL("CREATE TABLE {name} %s;").format(name=Identifier(name)),
vars=[coulmn]
)
def create_tables(self, names: list, coulmn: str):
"""This function is create new tables in database of instance connection.
Args:
names : Names of the table to be created.
coulmn : Column in the table to be created.
Format is "(name data_type condition, name2 data_type2 condition2...)".
"""
for name in names:
self.cur.execute(
query=SQL("CREATE TABLE {name} %s;").format(name=Identifier(name)),
vars=[coulmn]
)
full code
def connect(self, dsn: str):
self.con = psycopg2.connect(dsn=dsn)
self.cur = self.con.cursor()
This is the source of the code I want to change.
def connect(self, dsn: User):
self.con = psycopg2.connect(dsn=User.dsn)
self.cur = self.con.cursor()
I want the connect function to take a user class as a parameter, not a simple string class, and refer to the dsn of the user class.
However, the User class does not appear in the visual studio code, so it cannot be specified.
Reference Image
Why can't the connect function read the User class?
you should be calling the class from its parent class :
def connect(self, dsn: PostgreSql.User):
self.con = psycopg2.connect(dsn=User.dsn)
self.cur = self.con.cursor()
and you should import annotations:
from __future__ import annotations

Keep getting "Property object at 0x" when unpickling a class instance

I am trying to set up a multithreaded server and client, and am currently sending information wrapped in a TCP module class. I am sending the data using pickle, and have run in to a problem where attempting to access instance variables after unpickling the data leads to "Property object at 0x", instead of the instance variable.
Here is the relevant server code:
data = self.clientSocket.recv(2048)
print(data)
message = pickle.loads(data)
header = message.header
self.currUser = message.user
if header == 'user-login':
print("[recv] New login request")
self.userLogin()
client code:
username = input("Username: ")
password = input("Password: ")
message = TCPmodule().withSocket("user-login", password, self.clientSocket)
message.user = username
print(message.header)
data = pickle.dumps(message)
self.clientSocket.send(data)
Class (classmethod used and getters/setters):
def withSocket(self, header, content, socket):
self.header = header
self.content = content
self.socket = socket
self.user = ""
self.port = 0
return self
#property
def header(self):
return self._header
#header.setter
def header(self,value):
self._header = value
#property
def content(self):
return self._content
#content.setter
def content(self,content):
self._content = content
#property
def user(self):
return self._user
#user.setter
def user(self,user):
self._user = user
property object message when I print (message.header) server side
Am somewhat new to python, so I'm not sure if I'm missing something here.
Thanks

what is the best creational pattern to apply for class to access different databases

i have an application written in python
currently there are around 5 classes that are used to access different databases.
Structure of these classes are like below (i know it is poorly designed):
class access_db_a:
def __init__(self, db):
self.mydb = None
def connect(self):
mydb = mysql.connector.connect(
host=info["db_2_host"],
user=info["user"],
passwd=info["passwd"],
database=info["db_2"],
)
def select(self):
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM {}".format(TABLE_NAME))
myresult = mycursor.fetchall()
for x in myresult:
print(x)
def insert(self):
mycursor = mydb.cursor()
query = {'queries for db'}
class access_db_b:
def __init__(self, db_2):
self.mydb = None
def connect(self, db_2):
mydb = mysql.connector.connect(
host=info["db_2_host"],
user=info["user"],
passwd=info["passwd"],
database=info["db_2"],
)
def select(self):
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM {}".format(TABLE_NAME))
myresult = mycursor.fetchall()
for x in myresult:
print(x)
def insert(self):
mycursor = mydb.cursor()
query = {'queries for db_2'}
My question is: what is the best creational design pattern to apply here (i.e. Signleton, Factory Method)? the purpose is to minimize the duplication
You might want to define a base class for mysql. This class can be separated in a file, maybe as your own library.
class mysqlBase():
def __init__(self, host, user, passwd, database):
self.host = host
self.user = user
self.passwd = passwd
self.database = database
self.db = None
def connect(self,):
self.db = mysql.connector.connect(
host = self.host,
user = self.user,
passwd = self.passwd,
database = self.database,
)
def select(self, tbl):
mycursor = self.db.cursor()
mycursor.execute("SELECT * FROM {}".format(tbl))
myresult = mycursor.fetchall()
for x in myresult:
print(x)
# more functions
# ...
then use it in your classes
class access_db_a():
def __init__(self, host, user, passwd, database):
self.mydb = mysqlBase(host, user, passwd, database)
def connect(self,):
self.mydb.connect()
def select(self, tbl):
self.mydb.select(tbl)
# more functions refer to mysqlBase()
# ...
or with class inheritance,
class access_db_a(
mysqlBase
):
def __init__(self, host, user, passwd, database):
mysqlBase.__init__(self, host, user, passwd, database)
# No need to define connect(), unless you wanna override it
# No need to define select(), unless you wanna override it
finally, in your code, call your class as object.
# Const
info = { # just some database const
'A': {
"host": "192.128.0.123",
"id": "AAA",
"pw": "aaa",
"db": "whatever",
},
}
dbA = access_db_a(**info['A']) # pass the login detail to your class
dbA.connect()
dbA.select('TABLE_A')
I'm not sure I understand what you are asking. If you are trying to call those definitions on the databases, you need to define them. As is they don't do anything. If they are functions that already exist in the python library or another module, then you don't need to put them in a class at all. You can just call them on the databases after you define them.
I'm not sure I understand what you are asking. If you are trying to call those definitions on the databases, you need to define them. As is they don't do anything. If they are functions that already exist in the python library or another module, then you don't need to put them in a class at all. You can just call them on the databases after you define them.
Also, if you are trying to make the functions to be attributes of the class, then you need an __init__() constructor function. like this:
class access_db_a():
def __init__(self):
self.connect = connect()
self.select = select()
self.insert = insert()

Integration test with native SQLAlchemy

I have some trouble with integration test. I'm using python 3.5, SQLAlchemy 1.2.0b3, latest docker image of postgresql. So, I wrote test:
# tests/integration/usecases/test_users_usecase.py
class TestGetUsersUsecase(unittest.TestCase):
def setUp(self):
Base.metadata.reflect(_pg)
Base.metadata.drop_all(_pg)
Base.metadata.create_all(_pg)
self._session = sessionmaker(bind=_pg, autoflush=True, autocommit=False, expire_on_commit=True)
self.session = self._session()
self.session.add(User(id=1, username='user1'))
self.session.commit()
self.pg = PostgresService(session=self.session)
def test_get_user(self):
expected = User(id=1, username='user1')
boilerplates.get_user_usecase(storage_service=self.pg, id=1, expected=expected)
# tests/boilerplates/usecases/user_usecases.py
def get_user_usecase(storage_service, id, expected):
u = GetUser(storage_service=storage_service)
actual = u.apply(id=id)
assert expected == actual
In usecase I did next:
# usecases/users.py
class GetUser(object):
"""
Usecase for getting user from storage service by Id
"""
def __init__(self, storage_service):
self.storage_service = storage_service
def apply(self, id):
user = self.storage_service.get_user_by_id(id=id)
if user is None:
raise UserDoesNotExists('User with id=\'%s\' does not exists' % id)
return user
storage_service.get_user_by_id looks like:
# infrastructure/postgres.py (method of Postgres class)
def get_user_by_id(self, id):
from anna.domain.user import User
return self.session.query(User).filter(User.id == id).one_or_none()
And it does not work in my integration test. But if I add print(actual) in test before assert - all is OK. I thought that my test is bad, I try many variants and all does not works. Also I tried return generator from storage_service.get_user_by_id() and it also does not work. What I did wrong? It works good only if print() was called in test.

Error when using a Python constructor

class fileDetails :
def __init__(self,host,usr,pwd,database):
self.host=host
self.usr.usr
self.pwd=pwd
self.database=database
def __init__(self,connection,sql,path):
self.connection=mysql_connection()
self.sql=sql
self.path=path
If I use the constructor then it gives an error:
onnetction = fileDetails('localhost',"root","",'bulsorbit')
TypeError: __init__() takes exactly 4 arguments (5 given)
The overloading of the constructor (or any other function) is not allowed in python. So you cannot define two __init__ functions for your class.
You can have a look to this post or this one
The main ideas are to use default values or to create 'alternate constructors' or to check the number and the type of your args in order to choose which method to apply.
def __init__(self, **args):
Then args will be a dictionary containing all the parameters. So you will be able to make the difference between
connection = fileDetails(host='localhost',usr="root",pwd="",database='bulsorbit')
and
connection = fileDetails(connection="...",sql="...",path="...")
Define a single constructor with optional arguments.
def __init__(self,host='host',usr='user',pwd='pwd',database='db',connection=None,sql=None,path=None):
if connection:
# however you want to store your connection
self.sql=sql
self.path=path
else:
self.host=host
self.usr.usr
self.pwd=pwd
self.database=database
Or something of the sort.
maybe you can use len() to choose the right branch:
class Foo(object):
def __init__(self, *args):
if len(args) == 4: # network
self.host = args[0]
self.user = args[1]
self.pwd = args[2]
self.database = args[3]
elif len(args) == 3: # database
self.connection = mysql_connection() # maybe it's args[0]?
self.sql = args[1]
self.path = args[2]
def main():
foo = Foo('localhost',"root","",'bulsorbit')
print foo.host
if __name__ == "__main__":
main()
# output
# localhost
but, sine Explicit is better than implicit. maybe this is workable too:
class Foo(object):
def __init__(self, initdata):
if initdata['style'] == 'network':
self.host = initdata['host']
self.usr = initdata['usr']
self.pwd = initdata['pwd']
self.database = initdata['database']
elif initdata[style] == 'database':
self.connection = mysql_connection()
self.sql = initdata['sql']
self.path = initdata['path']
def main():
data = dict({'style': 'network',
'host': 'localhost',
'usr': 'root',
'pwd': '',
'database': 'database'})
foo = Foo(data)
print foo.host
if __name__ == "__main__":
main()
# output
# localhost
In Python the functions in a class are stored internally in a dictionary (remember that constructors are just regular functions), and so only one function of the same name can exist. Therefore, when defining more than one functions with the same name the last one will overwrite all the previously defined ones and you'll end up with only one function.
I suggest you look into keyword and default arguments to see the proper way of achieving what you want.
Here's one way to achieve this:
class FileDetails:
def __init__(self, *args, **kwargs):
if len(args) == 3:
self.conn, self.sql, self.path = args
elif len(args) == 4:
self.host, self.usr, self.pw, self.db = args
else:
# handle appropriately
fd1 = FileDetail('connstring', 'select * from foo', '/some/path')
print fd1.conn, fd1.sql, fd1.path
fd2 = FileDetail('host', 'user', 'pass', 'somedb')
print fd2.conn, fd2.usr, fd2.pw, fd2.db
Of course, you should do the appropriate type checking and error handling in the constructor.
On the side note: if you really, really, reallllllyyy must do JiP (Java in Python) then multiple dispatch methods are possible with some additional code eg. here and even beter: here by BDFL.
Personally I try to avoid using them.

Categories

Resources