Home > Software engineering >  Python OOP Seperating a Class
Python OOP Seperating a Class

Time:06-24

I currently have a class called Client that has functions to log in to a website and interact with it using python requests. However, my log in functionality is somewhat complicated. I have to visit about 10 different endpoints to collect the correct cookies just to log in. Therefore, I have 10 different functions for the log in process to gather all these cookies which is cluttering up my Client class. I'm also using an instance variable self.session for each request to automatically keep my session cookies updated to the latest request.

class Client:
    def __init__(self):
        self.session = requests.Session()

    def login_func1(self, url, headers):
        resp = self.session.get(url, headers=headers)

    def login_func2(self, url, headers):
        resp = self.session.get(url, headers=headers)


    def login_func3(self, url, headers):
        resp = self.session.get(url, headers=headers)


    def login_func4(self, url, headers):
        resp = self.session.get(url, headers=headers)

..........
    def login_func10(self, url, headers):
        resp = self.session.get(url, headers=headers)
        
    def login(self, url, headers, username, password):
         self.loginin_func1(url, header)
         self.loginin_func2(url, header)
         self.loginin_func3(url, header)
         self.loginin_func4(url, header)
         ......
         self.loginin_func10(url, header)
         resp = self.session.get(url, payload = {'user':username, 'password':password}, headers=headers)
         if resp.status_code == 200:
             print('Successfully logged in!')


    def get_images(self, url, headers):
        #get images code here

    def get_table_data(self, url, headers):
        #get table data code here



I would like to separate the log in functionality possibly into another class. I'm not sure if I should just make a separate object called LogIn and pass the self.session variable to that class, or if I should somehow make LogIn inherit from Client. But, after the LogIn class finishes logging in, I would need to go back to Client to interact with the site. I'm not sure what the best way of seperating this could would be. I was initially thinking of something like below, but not sure if inheritance would be a better , or even possible option. Thanks!

from login import LogIn
class Client:
    def __init__(self):
        self.session = requests.Session()

    def login(self, url, headers):
        self.session = LogIn(self.session).login(url, headers, username, password)
        

    def get_images(self, url, headers):
        //get images code here

    def get_table_data(self, url, headers):
        //get table data code here

class LogIn:
    def __init__(self, session):
        self.session = session

    def login_func1(self, url, headers):
        resp = self.session.get(url, headers=headers)

    def login_func2(self, url, headers):
        resp = self.session.get(url, headers=headers)


    def login_func3(self, url, headers):
        resp = self.session.get(url, headers=headers)


    def login_func4(self, url, headers):
        resp = self.session.get(url, headers=headers)
..........
    def login_func10(self, url, headers):
        resp = self.session.get(url, headers=headers)

    def login(self, url, headers, username, password):
         self.loginin_func1(url, header)
         self.loginin_func2(url, header)
         self.loginin_func3(url, header)
         self.loginin_func4(url, header)
         ......
         self.loginin_func10(url, header)
         resp = self.session.get(url, payload = {'user':username, 'password':password}, headers=headers)
         if resp.status_code == 200:
             print('Successfully logged in!")
         return self.session

CodePudding user response:

Your idea of inheritance seems to be a good approach.

I would propose to let the LogIn class inherit from Session, this way you can use it to create the Session and customize it via your desired login functionality:

class Client:

    def __init__(self):
        self.session = LoginSession()

    def login(self, url, headers, username, password):
        self.session.login(url, headers, username, password)


class LoginSession(requests.Session):

    def login(self, url, headers, username, password):
        self.login_func1(url, headers)
        # [...]
        self.login_func10(url, headers)
        resp = self.get(
            url, payload={"user": username, "password": password}, headers=headers
        )
        if resp.status_code == 200:
            print("Successfully logged in!")
            
    def login_func1(self, url, headers):
        resp = self.get(url, headers=headers)

    # [...]
    def login_func10(self, url, headers):
        resp = self.get(url, headers=headers)

CodePudding user response:

It's a little hard to tell exactly what differs in your various login_funcN functions, since you've simplified the problem a bit too much for your example. But if the only thing that needs to change between the different login efforts is the URL and headers, you might consider packing that data up separately in a data structure, rather than using separate functions for each step. The data can be stored separately from the rest of the class, and so you might not need a second class at all (just a data structure to hold the login data).

cookie_gathering_data = [(cookie_url1, cookie_headers1),
                         (cookie_url2, cookie_headers2),
                         ...]

class Client:
    def login(self, cookie_data, url, headers, username, password):
        for cookie_url, cookie_headers in cookie_data:
            self.session.get(cookie_url, headers=cookie_headers)
        resp = self.session.get(url, payload={'user':username, 'password':password},
                                headers=headers)
        if resp.status_code == 200:
            print('Successfully logged in!')
  • Related