Managing resources#

Controlling a web browser with Selenium requires several components:

  • a browser installed on the machine you are working on. This is the application that controlled by Selenium.

  • a driver that makes the links between the installed application and your code. The driver allows Selenium to control the browser with commands you provide.

A good management on these components is essential to ensure the stability of your application. It can be easy to handle all of that in a dev environment but managing your resources in production can be trickier.

manen provides several functions and classes whose purpose is to provide simple interfaces to manage browsers and drivers.

An API around your browsers and drivers#

Each browser has its own sub-package (defined in manen.resource), each one of them providing at least two classes:

  • application, implementing some methods in order to get the status of the installed browser.

  • driver which is a class used as interface with the driver resources, enabling to list and download any drivers available online.

For now, only two browsers are fully supported by manen: Google Chrome and Brave. The support for other browsers such as Firefox is planned in the coming release.

In the following example, we will work with Chrome.

[1]:
from manen.resource import chrome

Thanks to the application class, we can check that the browser is correctly installed and retrieve the current version.

[2]:
assert chrome.application.is_installed()
chrome_version = chrome.application.installed_version()
chrome_version
[2]:
(98, 0, 4758, 102)

manen also provides the same interface for the browser Brave.

[3]:
from manen.resource import brave
[4]:
assert brave.application.is_installed()
brave_version = brave.application.installed_version()
brave_version
[4]:
(98, 1, 35, 101)

ℹ All browser resource managers provided by manen will have slightly the same interface, and can be imported using the same path manen.resource.{browser_name}.

Thanks to the application interface, we checked that the first component needed to work with Selenium (the browser) is correctly installed.

Let’s interact with the second component: the driver. First step will be to list all the versions for the Chromedriver assets available online. To restrict the number of results, we will focus on the versions matching the installed version of Google Chrome.

[5]:
available_drivers = chrome.driver.list_versions(query='97.0.4692')
available_drivers
[5]:
[{'version': (97, 0, 4692, 20),
  'name': 'chromedriver_mac64.zip',
  'updated_at': '2021-11-19T10:02:37.708Z',
  'size': 8258658},
 {'version': (97, 0, 4692, 36),
  'name': 'chromedriver_mac64.zip',
  'updated_at': '2021-12-03T08:12:33.544Z',
  'size': 8277983},
 {'version': (97, 0, 4692, 71),
  'name': 'chromedriver_mac64.zip',
  'updated_at': '2022-01-05T05:45:13.182Z',
  'size': 8277283}]

You can also use the method latest_release to get the version number of the last chromedriver available. If Google Chrome is fully updated, you will be able to use this version to control the browser.

[6]:
latest_release = chrome.driver.latest_release()
latest_release
[6]:
(98, 0, 4758, 102)

Now that we have a version of the Chromedriver compatible with our installed Chrome, let’s download the binary file in order to be able to use it locally with Selenium. The drivers resource manager provides a method that will fetch the chromedriver archive and unzip it.

Once downloaded, the driver will be stored in a folder inside manen directory, with the following path:

{manen_directory}/assets/drivers/{platform}/{browser}/{version}/{driver_name}

where:

  • manen_directory can be obtained with manen.resource.local.LocalAsset.PATH

  • platform is specific to the OS of the machine (for example on a Mac, it will be “darwin”)

  • version is the version of the driver requested

  • driver_name is the name of the downloaded driver (“chromedriver” for Google Chrome and Brave)

[7]:
# A function to hide the path that is specific to each environment
import re
obfuscate = lambda path: re.sub('/Users/.*?/manen/', '/***/', path)
[8]:
chromedriver_path = chrome.driver.download(version=latest_release)
obfuscate(chromedriver_path)
[8]:
'/***/manen/assets/drivers/darwin/chrome/98.0.4758.102/chromedriver'

The download will always retrieve the file online; if the driver has already been downloaded, you can instead use the method get. This method will first check that the driver is not available locally and, if not, download it.

For example, the following command will check if the last release for the Chromedriver 97.*.*.* is available in the local file sytem and download it if not. In any case, it returns the chromedriver path, that should be specified when instaciating a WebDriver.

[9]:
chromedriver_path = chrome.driver.get(query='97')
obfuscate(chromedriver_path)
[9]:
'/***/manen/assets/drivers/darwin/chrome/97.0.4692.71/chromedriver'

Once downloaded, you can retrieved all the installed files using manen.resource.local.LocalAsset.

[10]:
from manen.resource.local import LocalAsset as local
[11]:
obfuscate = lambda item: {**item, 'path': re.sub('/Users/.*?/manen/', '/***/', item['path'])}
[12]:
[obfuscate(item) for item in local.list_drivers(browser='chrome')]
[12]:
[{'path': '/***/manen/assets/drivers/darwin/chrome/98.0.4758.102/chromedriver',
  'version': '98.0.4758',
  'browser': 'chrome',
  'os': 'darwin'},
 {'path': '/***/manen/assets/drivers/darwin/chrome/97.0.4692.71/chromedriver',
  'version': '97.0.4692',
  'browser': 'chrome',
  'os': 'darwin'}]

Using the CLI#

The download of browser drivers can be done through manen CLI instead of using classes driver.

[13]:
%%bash
manen driver download -h
usage: manen driver download [-h] [-i] [-b {chrome,brave}] [-p {Darwin,Linux}]
                             [-v VERSION [VERSION ...]]

Download one or several drivers for a specific browser on a given OS.

optional arguments:
  -h, --help            show this help message and exit
  -i, --interactive     Set the specifications for the download through a
                        serie of interactive questions. If specified, the
                        options of the specifications group must not be set.

specifications:
  -b {chrome,brave}, --browser {chrome,brave}
                        Browser that will be used to launch the Selenium/manen
                        application.
  -p {Darwin,Linux}, --platform {Darwin,Linux}
                        Platform (OS) on which the driver binary will run.
                        Note that 'Darwin' is for MacOS and you can use the
                        alias 'Mac' for this OS.
  -v VERSION [VERSION ...], --version VERSION [VERSION ...]
                        List of driver versions to be downloaded

Let’s download all the drivers we need with the CLI. At the end, the drivers will be available at the same location as it was downloaded through the API.

$ manen driver download -i
» Starting interactive CLI to download webdrivers...
? What is your OS? Mac OS
? For which browser do you want to download the drivers? Chrome / Brave
? Choose the version you want to download. (Use arrow keys to move, <space> to select, <a> to toggle, <i> to invert)
    95.0.4638.17
    95.0.4638.54
    95.0.4638.69
    96.0.4664.18
    96.0.4664.35
    96.0.4664.45
    97.0.4692.20 (compatible with Chrome)
    97.0.4692.36 (compatible with Chrome)
 »  97.0.4692.71 (compatible with Chrome)
    98.0.4758.48