-1

I have created a singleton wrapper for the selenium webdriver.

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Driver(metaclass=Singleton):   
        """Ensures theres only 1 Driver open at any time.
        If the driver is closed, tries to quit the previous
        instance, and recreates a new one"""

        def __init__(self):
            self._driver = self.load_selenium_driver()

    @staticmethod
    def load_selenium_driver():
        _chrome_driver_locn = CHROME_DRIVER_LOCATION
        _driver =  webdriver.Chrome(_chrome_driver_locn)
        return _driver

    @property
    def driver(self):
        """Creates a new driver if the previous one is closed,
        and quits the instance of the chrome driver."""
        if self._web_browser_is_open():
            return self._driver
        else:
            try:
                self._driver.quit()
            finally:
                self._driver = self.load_selenium_driver()
                return self._driver

    def _web_browser_is_open(self):
        try:
            self._driver.title
            return True
        except WebDriverException:
            return False

Running a = Driver() I want to access the Driver.driver methods, in a, so that I don't need to do a.driver.get('google.com'), but a.get('google.com').

The question:

How do I make an instance of Driver, return the driver object (found in the property Driver.driver), rather than the instance of the Driver?

A H
  • 2,164
  • 1
  • 21
  • 36
  • `Foo()` does not 'call' a class instance, it creates one. Why do you want to do this? What is the background of your question? –  Apr 27 '18 at 09:34
  • 2
    Why not just use `a = 5` then? – khelwood Apr 27 '18 at 09:35
  • I have edited it to make my question more clear. – A H Apr 27 '18 at 09:35
  • We already understood your question without the edit. But your question makes no sense. –  Apr 27 '18 at 09:36
  • I am trying to create a singleton wrapper for a selnium driver. I have made it, but to access the driver I must do `a = Driver()` `a.driver.get('http://google.com')` I want to do just, `a.get('http://google.com')` give me the same thing. – A H Apr 27 '18 at 09:37
  • Okay I just voted to close as duplicate but your comment brings more light to the question and I take my vote back. :D Can you add it to the question please? – Kos Apr 27 '18 at 09:38
  • thanks, any idea how pandas dataframes do it? – A H Apr 27 '18 at 09:39
  • 1
    Using an identifier expression will always return the object that the identifier is bound to. It will not return something else. What do you mean pandas dataframes do it? – juanpa.arrivillaga Apr 27 '18 at 09:39
  • 2
    @AH What you're asking for in the comments and what your question is asking for are two completely different things – TerryA Apr 27 '18 at 09:39
  • The question is a simplified example, I'll put my full question in there I guess. – A H Apr 27 '18 at 09:40
  • @TerryA I think the OP is committing the common error of referring to simple identifier expressions as "calling" the object. – juanpa.arrivillaga Apr 27 '18 at 09:42
  • 1
    I've reopened the question and removed the beginning code (and replaced it with the more relevant code) – TerryA Apr 27 '18 at 09:44
  • Again, `a` can only ever refer to the object it is bound to. This is part of the [language](https://docs.python.org/3.6/reference/expressions.html#atom-identifiers) – juanpa.arrivillaga Apr 27 '18 at 09:47
  • so how do pandas dataframes do it? `x = pd.DataFrame([1,2,3])` `x` -> returns the dataframe object. I want `a` to return my driver object. – A H Apr 27 '18 at 09:49
  • ... `pd.DataFrame([1,2,3]) ` **is a dataframe object**. That is what `x` is bound to. Thus, that is what `x` evaluates to. `a` is bound to a `Driver` object. It will always return that drive object until you reassign the name or delete the name. It cannot evaluate to a `webdriver.Chrome` object without assigning one to it. I don't understand what you think is different about `pd.DataFrame` and your `Driver` class. – juanpa.arrivillaga Apr 27 '18 at 09:51
  • Okay, so I guess the solution would be `driver = Driver()` `driver = driver.driver`? Seems very unpythonic to me. – A H Apr 27 '18 at 09:53
  • I am not sure if I have understood your question but... You could try `a = Drive()` and then `b = a.driver` so that you can do `b.get('http://google.com')`. Since `driver` is a `property` this might work. This is just a shoot in the air as I have no chance to check wthat I am saying. – kazbeel Apr 27 '18 at 09:54
  • @AH what is unpythonic about it? What is unpythonic about names evaluating to the objects they are bound to? I am honestly curious about what you mean regarding `pd.DataFrame`. You seem to have some fundamental misunderstanding, but it's not clear to me what exactly it is. – juanpa.arrivillaga Apr 27 '18 at 09:57
  • Because I would have to do that each time I instantiate the class (say it was not a singleton, but something else), which would have defeated the DRY principle. I would have thought there would have been a better way. I guess not, thanks anyways. – A H Apr 27 '18 at 10:00
  • @AH how is that different from any other attribute/method? Anyay, `driver = driver.driver` is not semantically equivalent. It makes your whole `property` getter pointless. – juanpa.arrivillaga Apr 27 '18 at 10:01
  • I am not saying it is, I was just curious to see if there was a better way of doing it, thats all. – A H Apr 27 '18 at 10:04

1 Answers1

0

From the discussions in the comments, what I am asking for is not possible.

A H
  • 2,164
  • 1
  • 21
  • 36