From 3978a030c13f65dfadb58efe3d8ca8f56aa655ab Mon Sep 17 00:00:00 2001 From: AutomatedTester Date: Fri, 22 May 2026 12:13:43 +0100 Subject: [PATCH 1/2] [py][js] Initial Creation of a external shippable selenium manager this adds the ability to call npx or uvx to be able to call selenium manager and it handles the scenarios around picking the correct version for your computer --- common/manager/BUILD.bazel | 6 ++ .../selenium-manager-darwin/BUILD.bazel | 34 +++++++++ .../selenium-manager-darwin/package.json | 28 ++++++++ .../selenium-manager-linux-x64/BUILD.bazel | 34 +++++++++ .../selenium-manager-linux-x64/package.json | 29 ++++++++ javascript/selenium-manager-win32/BUILD.bazel | 34 +++++++++ .../selenium-manager-win32/package.json | 28 ++++++++ javascript/selenium-manager/BUILD.bazel | 27 +++++++ .../selenium-manager/bin/selenium-manager.js | 70 +++++++++++++++++++ javascript/selenium-manager/package.json | 45 ++++++++++++ py/selenium-manager-linux-x86-64/BUILD.bazel | 46 ++++++++++++ .../pyproject.toml | 27 +++++++ .../selenium_manager_linux_x86_64/__init__.py | 30 ++++++++ py/selenium-manager-macos/BUILD.bazel | 46 ++++++++++++ py/selenium-manager-macos/pyproject.toml | 27 +++++++ .../selenium_manager_macos/__init__.py | 30 ++++++++ py/selenium-manager-windows/BUILD.bazel | 46 ++++++++++++ py/selenium-manager-windows/pyproject.toml | 27 +++++++ .../selenium_manager_windows/__init__.py | 28 ++++++++ py/selenium-manager/BUILD.bazel | 56 +++++++++++++++ py/selenium-manager/pyproject.toml | 45 ++++++++++++ .../selenium_manager/__init__.py | 45 ++++++++++++ .../selenium_manager/__main__.py | 21 ++++++ rake_tasks/node.rake | 67 ++++++++++++++++++ rake_tasks/python.rake | 61 ++++++++++++++++ 25 files changed, 937 insertions(+) create mode 100644 javascript/selenium-manager-darwin/BUILD.bazel create mode 100644 javascript/selenium-manager-darwin/package.json create mode 100644 javascript/selenium-manager-linux-x64/BUILD.bazel create mode 100644 javascript/selenium-manager-linux-x64/package.json create mode 100644 javascript/selenium-manager-win32/BUILD.bazel create mode 100644 javascript/selenium-manager-win32/package.json create mode 100644 javascript/selenium-manager/BUILD.bazel create mode 100644 javascript/selenium-manager/bin/selenium-manager.js create mode 100644 javascript/selenium-manager/package.json create mode 100644 py/selenium-manager-linux-x86-64/BUILD.bazel create mode 100644 py/selenium-manager-linux-x86-64/pyproject.toml create mode 100644 py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py create mode 100644 py/selenium-manager-macos/BUILD.bazel create mode 100644 py/selenium-manager-macos/pyproject.toml create mode 100644 py/selenium-manager-macos/selenium_manager_macos/__init__.py create mode 100644 py/selenium-manager-windows/BUILD.bazel create mode 100644 py/selenium-manager-windows/pyproject.toml create mode 100644 py/selenium-manager-windows/selenium_manager_windows/__init__.py create mode 100644 py/selenium-manager/BUILD.bazel create mode 100644 py/selenium-manager/pyproject.toml create mode 100644 py/selenium-manager/selenium_manager/__init__.py create mode 100644 py/selenium-manager/selenium_manager/__main__.py diff --git a/common/manager/BUILD.bazel b/common/manager/BUILD.bazel index e38ecafdb98e6..bd54af810e535 100644 --- a/common/manager/BUILD.bazel +++ b/common/manager/BUILD.bazel @@ -3,8 +3,14 @@ package( "//dotnet/src/webdriver:__pkg__", "//dotnet/test/common:__pkg__", "//java/src/org/openqa/selenium/manager:__pkg__", + "//javascript/selenium-manager-darwin:__pkg__", + "//javascript/selenium-manager-linux-x64:__pkg__", + "//javascript/selenium-manager-win32:__pkg__", "//javascript/selenium-webdriver:__pkg__", "//py:__pkg__", + "//py/selenium-manager-linux-x86-64:__pkg__", + "//py/selenium-manager-macos:__pkg__", + "//py/selenium-manager-windows:__pkg__", "//rb:__pkg__", ], ) diff --git a/javascript/selenium-manager-darwin/BUILD.bazel b/javascript/selenium-manager-darwin/BUILD.bazel new file mode 100644 index 0000000000000..0c522478630fa --- /dev/null +++ b/javascript/selenium-manager-darwin/BUILD.bazel @@ -0,0 +1,34 @@ +load("@aspect_rules_js//npm:defs.bzl", "npm_package") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-macos", + out = "bin/selenium-manager", +) + +genrule( + name = "license", + srcs = ["//:license"], + outs = [ + "LICENSE", + "NOTICE", + ], + cmd = "cp $(locations //:license) $(@D)", +) + +npm_package( + name = "selenium-manager-darwin", + srcs = [ + "package.json", + ":license", + ":manager-binary", + ], + package = "@selenium/manager-darwin", + publishable = True, + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], +) diff --git a/javascript/selenium-manager-darwin/package.json b/javascript/selenium-manager-darwin/package.json new file mode 100644 index 0000000000000..a393f35beb0ec --- /dev/null +++ b/javascript/selenium-manager-darwin/package.json @@ -0,0 +1,28 @@ +{ + "name": "@selenium/manager-darwin", + "version": "4.45.0", + "description": "Selenium Manager binary for macOS (universal binary, x64 + arm64)", + "license": "Apache-2.0", + "os": ["darwin"], + "homepage": "https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/selenium-manager#readme", + "bugs": { + "url": "https://github.com/SeleniumHQ/selenium/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/SeleniumHQ/selenium.git" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/SeleniumHQ" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/selenium" + } + ] +} diff --git a/javascript/selenium-manager-linux-x64/BUILD.bazel b/javascript/selenium-manager-linux-x64/BUILD.bazel new file mode 100644 index 0000000000000..bf4a9c766b636 --- /dev/null +++ b/javascript/selenium-manager-linux-x64/BUILD.bazel @@ -0,0 +1,34 @@ +load("@aspect_rules_js//npm:defs.bzl", "npm_package") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-linux", + out = "bin/selenium-manager", +) + +genrule( + name = "license", + srcs = ["//:license"], + outs = [ + "LICENSE", + "NOTICE", + ], + cmd = "cp $(locations //:license) $(@D)", +) + +npm_package( + name = "selenium-manager-linux-x64", + srcs = [ + "package.json", + ":license", + ":manager-binary", + ], + package = "@selenium/manager-linux-x64", + publishable = True, + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], +) diff --git a/javascript/selenium-manager-linux-x64/package.json b/javascript/selenium-manager-linux-x64/package.json new file mode 100644 index 0000000000000..a3f0cc8ae6509 --- /dev/null +++ b/javascript/selenium-manager-linux-x64/package.json @@ -0,0 +1,29 @@ +{ + "name": "@selenium/manager-linux-x64", + "version": "4.45.0", + "description": "Selenium Manager binary for Linux x64", + "license": "Apache-2.0", + "os": ["linux"], + "cpu": ["x64"], + "homepage": "https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/selenium-manager#readme", + "bugs": { + "url": "https://github.com/SeleniumHQ/selenium/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/SeleniumHQ/selenium.git" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/SeleniumHQ" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/selenium" + } + ] +} diff --git a/javascript/selenium-manager-win32/BUILD.bazel b/javascript/selenium-manager-win32/BUILD.bazel new file mode 100644 index 0000000000000..4091c6b6f7e3e --- /dev/null +++ b/javascript/selenium-manager-win32/BUILD.bazel @@ -0,0 +1,34 @@ +load("@aspect_rules_js//npm:defs.bzl", "npm_package") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-windows", + out = "bin/selenium-manager.exe", +) + +genrule( + name = "license", + srcs = ["//:license"], + outs = [ + "LICENSE", + "NOTICE", + ], + cmd = "cp $(locations //:license) $(@D)", +) + +npm_package( + name = "selenium-manager-win32", + srcs = [ + "package.json", + ":license", + ":manager-binary", + ], + package = "@selenium/manager-win32", + publishable = True, + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], +) diff --git a/javascript/selenium-manager-win32/package.json b/javascript/selenium-manager-win32/package.json new file mode 100644 index 0000000000000..a8e7ce7857590 --- /dev/null +++ b/javascript/selenium-manager-win32/package.json @@ -0,0 +1,28 @@ +{ + "name": "@selenium/manager-win32", + "version": "4.45.0", + "description": "Selenium Manager binary for Windows (ia32 + x64)", + "license": "Apache-2.0", + "os": ["win32"], + "homepage": "https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/selenium-manager#readme", + "bugs": { + "url": "https://github.com/SeleniumHQ/selenium/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/SeleniumHQ/selenium.git" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/SeleniumHQ" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/selenium" + } + ] +} diff --git a/javascript/selenium-manager/BUILD.bazel b/javascript/selenium-manager/BUILD.bazel new file mode 100644 index 0000000000000..4e281ebd80fce --- /dev/null +++ b/javascript/selenium-manager/BUILD.bazel @@ -0,0 +1,27 @@ +load("@aspect_rules_js//npm:defs.bzl", "npm_package") + +SM_VERSION = "4.45.0" + +genrule( + name = "license", + srcs = ["//:license"], + outs = [ + "LICENSE", + "NOTICE", + ], + cmd = "cp $(locations //:license) $(@D)", +) + +npm_package( + name = "selenium-manager", + srcs = [ + "bin/selenium-manager.js", + "package.json", + ":license", + ], + package = "@selenium/manager", + publishable = True, + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], +) diff --git a/javascript/selenium-manager/bin/selenium-manager.js b/javascript/selenium-manager/bin/selenium-manager.js new file mode 100644 index 0000000000000..e8f6069c973f8 --- /dev/null +++ b/javascript/selenium-manager/bin/selenium-manager.js @@ -0,0 +1,70 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +'use strict' + +const { execFileSync } = require('node:child_process') +const path = require('node:path') +const fs = require('node:fs') +const { platform } = require('node:process') + +const PLATFORM_PACKAGES = { + linux: '@selenium/manager-linux-x64', + darwin: '@selenium/manager-darwin', + win32: '@selenium/manager-win32', + cygwin: '@selenium/manager-win32', +} + +function getBinaryPath() { + if (process.env.SE_MANAGER_PATH) { + return process.env.SE_MANAGER_PATH + } + + const pkgName = PLATFORM_PACKAGES[platform] + if (!pkgName) { + throw new Error( + `Unsupported platform: ${platform}. ` + + `Supported: linux, darwin, win32` + ) + } + + const isWindows = platform === 'win32' || platform === 'cygwin' + const binaryName = isWindows ? 'selenium-manager.exe' : 'selenium-manager' + + let pkgJsonPath + try { + pkgJsonPath = require.resolve(`${pkgName}/package.json`) + } catch (_) { + throw new Error( + `Platform package ${pkgName} is not installed. ` + + `Run: npm install ${pkgName}` + ) + } + + const binPath = path.join(path.dirname(pkgJsonPath), 'bin', binaryName) + if (!fs.existsSync(binPath)) { + throw new Error(`Binary not found at expected path: ${binPath}`) + } + return binPath +} + +const binary = getBinaryPath() +try { + execFileSync(binary, process.argv.slice(2), { stdio: 'inherit' }) +} catch (err) { + process.exit(err.status ?? 1) +} diff --git a/javascript/selenium-manager/package.json b/javascript/selenium-manager/package.json new file mode 100644 index 0000000000000..6790ef1a561b3 --- /dev/null +++ b/javascript/selenium-manager/package.json @@ -0,0 +1,45 @@ +{ + "name": "@selenium/manager", + "version": "4.45.0", + "description": "Selenium Manager — browser and driver manager for the Selenium ecosystem", + "license": "Apache-2.0", + "keywords": [ + "automation", + "selenium", + "testing", + "webdriver", + "browser-manager" + ], + "homepage": "https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/selenium-manager#readme", + "bugs": { + "url": "https://github.com/SeleniumHQ/selenium/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/SeleniumHQ/selenium.git" + }, + "engines": { + "node": ">= 18.0.0" + }, + "bin": { + "selenium-manager": "./bin/selenium-manager.js" + }, + "optionalDependencies": { + "@selenium/manager-darwin": "4.45.0", + "@selenium/manager-linux-x64": "4.45.0", + "@selenium/manager-win32": "4.45.0" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/SeleniumHQ" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/selenium" + } + ] +} diff --git a/py/selenium-manager-linux-x86-64/BUILD.bazel b/py/selenium-manager-linux-x86-64/BUILD.bazel new file mode 100644 index 0000000000000..89dda627a2dd5 --- /dev/null +++ b/py/selenium-manager-linux-x86-64/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_python//python:defs.bzl", "py_library") +load("@rules_python//python:packaging.bzl", "py_wheel") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-linux", + out = "selenium_manager_linux_x86_64/bin/selenium-manager", +) + +py_library( + name = "lib", + srcs = ["selenium_manager_linux_x86_64/__init__.py"], + data = [":manager-binary"], + imports = ["."], +) + +py_wheel( + name = "selenium-manager-linux-x86-64-wheel", + abi = "none", + classifiers = [ + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", + ], + description_content_type = "text/plain", + distribution = "selenium_manager_linux_x86_64", + entry_points = { + "console_scripts": { + "selenium-manager": "selenium_manager_linux_x86_64:main", + }, + }, + homepage = "https://www.selenium.dev", + license = "Apache-2.0", + platform = "linux_x86_64", + python_requires = ">=3.9", + python_tag = "py3", + strip_path_prefixes = ["py/selenium-manager-linux-x86-64/"], + summary = "Selenium Manager binary for Linux x86-64", + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], + deps = [":lib"], +) diff --git a/py/selenium-manager-linux-x86-64/pyproject.toml b/py/selenium-manager-linux-x86-64/pyproject.toml new file mode 100644 index 0000000000000..8e5c44079dce0 --- /dev/null +++ b/py/selenium-manager-linux-x86-64/pyproject.toml @@ -0,0 +1,27 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "selenium-manager-linux-x86-64" +version = "4.45.0" +license = "Apache-2.0" +license-files = ["LICENSE", "NOTICE"] +description = "Selenium Manager binary for Linux x86-64" +requires-python = ">=3.9" +classifiers = [ + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", +] + +[project.urls] +homepage = "https://www.selenium.dev" +source = "https://github.com/SeleniumHQ/selenium/tree/trunk/py/selenium-manager-linux-x86-64" +issues = "https://github.com/SeleniumHQ/selenium/issues" + +[project.scripts] +selenium-manager = "selenium_manager_linux_x86_64:main" + +[tool.setuptools.package-data] +selenium_manager_linux_x86_64 = ["bin/selenium-manager"] diff --git a/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py b/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py new file mode 100644 index 0000000000000..160c82c177c2f --- /dev/null +++ b/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py @@ -0,0 +1,30 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import importlib.resources +import os +import subprocess +import sys + + +def main() -> None: + with importlib.resources.as_file( + importlib.resources.files(__package__) / "bin" / "selenium-manager" + ) as binary: + os.chmod(binary, os.stat(binary).st_mode | 0o755) + result = subprocess.run([str(binary)] + sys.argv[1:]) + sys.exit(result.returncode) diff --git a/py/selenium-manager-macos/BUILD.bazel b/py/selenium-manager-macos/BUILD.bazel new file mode 100644 index 0000000000000..3020b6793c042 --- /dev/null +++ b/py/selenium-manager-macos/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_python//python:defs.bzl", "py_library") +load("@rules_python//python:packaging.bzl", "py_wheel") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-macos", + out = "selenium_manager_macos/bin/selenium-manager", +) + +py_library( + name = "lib", + srcs = ["selenium_manager_macos/__init__.py"], + data = [":manager-binary"], + imports = ["."], +) + +py_wheel( + name = "selenium-manager-macos-wheel", + abi = "none", + classifiers = [ + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", + ], + description_content_type = "text/plain", + distribution = "selenium_manager_macos", + entry_points = { + "console_scripts": { + "selenium-manager": "selenium_manager_macos:main", + }, + }, + homepage = "https://www.selenium.dev", + license = "Apache-2.0", + platform = "macosx_10_13_universal2", + python_requires = ">=3.9", + python_tag = "py3", + strip_path_prefixes = ["py/selenium-manager-macos/"], + summary = "Selenium Manager binary for macOS (universal binary, x86-64 + aarch64)", + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], + deps = [":lib"], +) diff --git a/py/selenium-manager-macos/pyproject.toml b/py/selenium-manager-macos/pyproject.toml new file mode 100644 index 0000000000000..9dce1cd9d4a0e --- /dev/null +++ b/py/selenium-manager-macos/pyproject.toml @@ -0,0 +1,27 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "selenium-manager-macos" +version = "4.45.0" +license = "Apache-2.0" +license-files = ["LICENSE", "NOTICE"] +description = "Selenium Manager binary for macOS (universal binary, x86-64 + aarch64)" +requires-python = ">=3.9" +classifiers = [ + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", +] + +[project.urls] +homepage = "https://www.selenium.dev" +source = "https://github.com/SeleniumHQ/selenium/tree/trunk/py/selenium-manager-macos" +issues = "https://github.com/SeleniumHQ/selenium/issues" + +[project.scripts] +selenium-manager = "selenium_manager_macos:main" + +[tool.setuptools.package-data] +selenium_manager_macos = ["bin/selenium-manager"] diff --git a/py/selenium-manager-macos/selenium_manager_macos/__init__.py b/py/selenium-manager-macos/selenium_manager_macos/__init__.py new file mode 100644 index 0000000000000..160c82c177c2f --- /dev/null +++ b/py/selenium-manager-macos/selenium_manager_macos/__init__.py @@ -0,0 +1,30 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import importlib.resources +import os +import subprocess +import sys + + +def main() -> None: + with importlib.resources.as_file( + importlib.resources.files(__package__) / "bin" / "selenium-manager" + ) as binary: + os.chmod(binary, os.stat(binary).st_mode | 0o755) + result = subprocess.run([str(binary)] + sys.argv[1:]) + sys.exit(result.returncode) diff --git a/py/selenium-manager-windows/BUILD.bazel b/py/selenium-manager-windows/BUILD.bazel new file mode 100644 index 0000000000000..765fefd1f45aa --- /dev/null +++ b/py/selenium-manager-windows/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_python//python:defs.bzl", "py_library") +load("@rules_python//python:packaging.bzl", "py_wheel") +load("//common:defs.bzl", "copy_file") + +SM_VERSION = "4.45.0" + +copy_file( + name = "manager-binary", + src = "//common/manager:selenium-manager-windows", + out = "selenium_manager_windows/bin/selenium-manager.exe", +) + +py_library( + name = "lib", + srcs = ["selenium_manager_windows/__init__.py"], + data = [":manager-binary"], + imports = ["."], +) + +py_wheel( + name = "selenium-manager-windows-wheel", + abi = "none", + classifiers = [ + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", + ], + description_content_type = "text/plain", + distribution = "selenium_manager_windows", + entry_points = { + "console_scripts": { + "selenium-manager": "selenium_manager_windows:main", + }, + }, + homepage = "https://www.selenium.dev", + license = "Apache-2.0", + platform = "win32", + python_requires = ">=3.9", + python_tag = "py3", + strip_path_prefixes = ["py/selenium-manager-windows/"], + summary = "Selenium Manager binary for Windows (ia32 + x64)", + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], + deps = [":lib"], +) diff --git a/py/selenium-manager-windows/pyproject.toml b/py/selenium-manager-windows/pyproject.toml new file mode 100644 index 0000000000000..ddae3bc73ddc8 --- /dev/null +++ b/py/selenium-manager-windows/pyproject.toml @@ -0,0 +1,27 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "selenium-manager-windows" +version = "4.45.0" +license = "Apache-2.0" +license-files = ["LICENSE", "NOTICE"] +description = "Selenium Manager binary for Windows (ia32 + x64)" +requires-python = ">=3.9" +classifiers = [ + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Topic :: Software Development :: Testing", +] + +[project.urls] +homepage = "https://www.selenium.dev" +source = "https://github.com/SeleniumHQ/selenium/tree/trunk/py/selenium-manager-windows" +issues = "https://github.com/SeleniumHQ/selenium/issues" + +[project.scripts] +selenium-manager = "selenium_manager_windows:main" + +[tool.setuptools.package-data] +selenium_manager_windows = ["bin/selenium-manager.exe"] diff --git a/py/selenium-manager-windows/selenium_manager_windows/__init__.py b/py/selenium-manager-windows/selenium_manager_windows/__init__.py new file mode 100644 index 0000000000000..e9c40f32ef69a --- /dev/null +++ b/py/selenium-manager-windows/selenium_manager_windows/__init__.py @@ -0,0 +1,28 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import importlib.resources +import subprocess +import sys + + +def main() -> None: + with importlib.resources.as_file( + importlib.resources.files(__package__) / "bin" / "selenium-manager.exe" + ) as binary: + result = subprocess.run([str(binary)] + sys.argv[1:]) + sys.exit(result.returncode) diff --git a/py/selenium-manager/BUILD.bazel b/py/selenium-manager/BUILD.bazel new file mode 100644 index 0000000000000..ee4dfcdb31794 --- /dev/null +++ b/py/selenium-manager/BUILD.bazel @@ -0,0 +1,56 @@ +load("@rules_python//python:defs.bzl", "py_library") +load("@rules_python//python:packaging.bzl", "py_wheel") + +SM_VERSION = "4.45.0" + +py_library( + name = "lib", + srcs = [ + "selenium_manager/__init__.py", + "selenium_manager/__main__.py", + ], + imports = ["."], +) + +py_wheel( + name = "selenium-manager-wheel", + abi = "none", + classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Topic :: Software Development :: Testing", + "Topic :: Software Development :: Libraries", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + ], + description_content_type = "text/x-rst", + distribution = "selenium_manager", + entry_points = { + "console_scripts": { + "selenium-manager": "selenium_manager:main", + }, + }, + homepage = "https://www.selenium.dev", + license = "Apache-2.0", + platform = "any", + python_requires = ">=3.9", + python_tag = "py3", + requires = [ + "selenium-manager-linux-x86-64==4.45.0; sys_platform=='linux' and platform_machine=='x86_64'", + "selenium-manager-macos==4.45.0; sys_platform=='darwin'", + "selenium-manager-windows==4.45.0; sys_platform=='win32'", + ], + strip_path_prefixes = ["py/selenium-manager/"], + summary = "Selenium Manager — browser and driver manager for the Selenium ecosystem", + tags = ["release-artifact"], + version = SM_VERSION, + visibility = ["//visibility:public"], + deps = [":lib"], +) diff --git a/py/selenium-manager/pyproject.toml b/py/selenium-manager/pyproject.toml new file mode 100644 index 0000000000000..a89c03c6202a2 --- /dev/null +++ b/py/selenium-manager/pyproject.toml @@ -0,0 +1,45 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "selenium-manager" +version = "4.45.0" +license = "Apache-2.0" +license-files = ["LICENSE", "NOTICE"] +description = "Selenium Manager — browser and driver manager for the Selenium ecosystem" +readme = "README.rst" +requires-python = ">=3.9" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Topic :: Software Development :: Testing", + "Topic :: Software Development :: Libraries", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [ + "selenium-manager-linux-x86-64==4.45.0; sys_platform=='linux' and platform_machine=='x86_64'", + "selenium-manager-macos==4.45.0; sys_platform=='darwin'", + "selenium-manager-windows==4.45.0; sys_platform=='win32'", +] + +[project.scripts] +selenium-manager = "selenium_manager:main" + +[project.urls] +homepage = "https://www.selenium.dev" +source = "https://github.com/SeleniumHQ/selenium/tree/trunk/py/selenium-manager" +download = "https://pypi.org/project/selenium-manager" +documentation = "https://www.selenium.dev/documentation/selenium_manager" +issues = "https://github.com/SeleniumHQ/selenium/issues" + +[tool.setuptools.packages.find] +include = ["selenium_manager*"] diff --git a/py/selenium-manager/selenium_manager/__init__.py b/py/selenium-manager/selenium_manager/__init__.py new file mode 100644 index 0000000000000..0e4d8b23254e2 --- /dev/null +++ b/py/selenium-manager/selenium_manager/__init__.py @@ -0,0 +1,45 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import importlib +import sys + +_PLATFORM_MODULES = { + "linux": "selenium_manager_linux_x86_64", + "darwin": "selenium_manager_macos", + "win32": "selenium_manager_windows", +} + + +def main() -> None: + module_name = _PLATFORM_MODULES.get(sys.platform) + if module_name is None: + raise SystemExit( + f"Unsupported platform: {sys.platform}. " + f"Supported: linux, darwin, win32" + ) + + try: + platform_module = importlib.import_module(module_name) + except ImportError as exc: + pkg_name = module_name.replace("_", "-") + raise SystemExit( + f"Platform package {pkg_name} is not installed.\n" + f"Run: pip install {pkg_name}" + ) from exc + + platform_module.main() diff --git a/py/selenium-manager/selenium_manager/__main__.py b/py/selenium-manager/selenium_manager/__main__.py new file mode 100644 index 0000000000000..73868009387a8 --- /dev/null +++ b/py/selenium-manager/selenium_manager/__main__.py @@ -0,0 +1,21 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from selenium_manager import main + +if __name__ == "__main__": + main() diff --git a/rake_tasks/node.rake b/rake_tasks/node.rake index d179b281ce95a..4139cb553ec37 100644 --- a/rake_tasks/node.rake +++ b/rake_tasks/node.rake @@ -6,6 +6,23 @@ def node_version end end +def manager_npm_version + File.foreach('javascript/selenium-manager/package.json') do |line| + return line.split(':').last.strip.tr('",', '') if line.include?('version') + end +end + +MANAGER_NPM_FILES = %w[ + javascript/selenium-manager/package.json + javascript/selenium-manager/BUILD.bazel + javascript/selenium-manager-darwin/package.json + javascript/selenium-manager-darwin/BUILD.bazel + javascript/selenium-manager-linux-x64/package.json + javascript/selenium-manager-linux-x64/BUILD.bazel + javascript/selenium-manager-win32/package.json + javascript/selenium-manager-win32/BUILD.bazel +].freeze unless defined?(MANAGER_NPM_FILES) + def setup_github_npm_auth token = ENV.fetch('GITHUB_TOKEN', nil) raise 'Missing GitHub token: set GITHUB_TOKEN for nightly npm publish' if token.nil? || token.empty? @@ -84,6 +101,40 @@ task :release do |_task, arguments| Bazel.execute('run', bazel_args, target) end +desc 'Release @selenium/manager standalone packages to npm (use dry-run to test without publishing)' +task :release_manager do |_task, arguments| + args = arguments.to_a + nightly = args.delete('nightly') + dry_run = args.delete('dry-run') + + Rake::Task['node:check_credentials'].invoke(*(nightly ? ['nightly'] : [])) unless dry_run + + if nightly + puts 'Updating @selenium/manager version to nightly...' + old_version = manager_npm_version + nightly_suffix = "-nightly#{Time.now.strftime('%Y%m%d%H%M')}" + base = old_version.split('-').first + new_version = "#{base}#{nightly_suffix}" + Rake::Task['node:version_manager'].invoke(new_version) + setup_github_npm_auth unless dry_run + end + + bazel_args = ['--config=release'] + bazel_args += ['--', '--dry-run=true'] if dry_run + + targets = [ + '//javascript/selenium-manager-linux-x64:selenium-manager-linux-x64.publish', + '//javascript/selenium-manager-darwin:selenium-manager-darwin.publish', + '//javascript/selenium-manager-win32:selenium-manager-win32.publish', + '//javascript/selenium-manager:selenium-manager.publish', + ] + + targets.each do |target| + puts dry_run ? "Dry-run: #{target}" : "Publishing: #{target}" + Bazel.execute('run', bazel_args, target) + end +end + desc 'Verify Node package is published on npm' task :verify do SeleniumRake.verify_package_published("https://registry.npmjs.org/selenium-webdriver/#{node_version}") @@ -133,6 +184,22 @@ task :version, [:version] do |_task, arguments| text = File.read(file).gsub(old_version, new_version) File.open(file, 'w') { |f| f.puts text } end + + Rake::Task['node:version_manager'].invoke(new_version) +end + +desc 'Update @selenium/manager package versions' +task :version_manager, [:new_version] do |_task, arguments| + new_version = arguments[:new_version] + raise 'new_version argument required' if new_version.nil? || new_version.empty? + + old_version = manager_npm_version + puts "Updating @selenium/manager packages from #{old_version} to #{new_version}" + + MANAGER_NPM_FILES.each do |file| + text = File.read(file).gsub(old_version, new_version) + File.open(file, 'w') { |f| f.puts text } + end end desc 'Format JavaScript code with prettier' diff --git a/rake_tasks/python.rake b/rake_tasks/python.rake index 1e9570602c752..f27cf9ce6fe47 100644 --- a/rake_tasks/python.rake +++ b/rake_tasks/python.rake @@ -8,6 +8,30 @@ def python_version end end +def manager_python_version + File.foreach('py/selenium-manager/BUILD.bazel') do |line| + return line.split('=').last.strip.tr('"', '') if line.include?('SM_VERSION') + end +end + +MANAGER_PYTHON_FILES = %w[ + py/selenium-manager/pyproject.toml + py/selenium-manager/BUILD.bazel + py/selenium-manager-linux-x86-64/pyproject.toml + py/selenium-manager-linux-x86-64/BUILD.bazel + py/selenium-manager-macos/pyproject.toml + py/selenium-manager-macos/BUILD.bazel + py/selenium-manager-windows/pyproject.toml + py/selenium-manager-windows/BUILD.bazel +].freeze unless defined?(MANAGER_PYTHON_FILES) + +MANAGER_PYTHON_WHEEL_TARGETS = %w[ + //py/selenium-manager-linux-x86-64:selenium-manager-linux-x86-64-wheel + //py/selenium-manager-macos:selenium-manager-macos-wheel + //py/selenium-manager-windows:selenium-manager-windows-wheel + //py/selenium-manager:selenium-manager-wheel +].freeze unless defined?(MANAGER_PYTHON_WHEEL_TARGETS) + desc 'Build Python wheel and sdist with optional arguments' task :build do |_task, arguments| args = arguments.to_a @@ -162,6 +186,43 @@ task :version, [:version] do |_task, arguments| conf = 'py/docs/source/conf.py' text = File.read(conf).gsub(old_short_version, new_short_version) File.open(conf, 'w') { |f| f.puts text } + + Rake::Task['py:version_manager'].invoke(new_version) +end + +desc 'Update selenium-manager Python package versions' +task :version_manager, [:new_version] do |_task, arguments| + new_version = arguments[:new_version] + raise 'new_version argument required' if new_version.nil? || new_version.empty? + + old_version = manager_python_version + puts "Updating selenium-manager Python packages from #{old_version} to #{new_version}" + + MANAGER_PYTHON_FILES.each do |file| + text = File.read(file).gsub(old_version, new_version) + File.open(file, 'w') { |f| f.puts text } + end +end + +desc 'Build and release selenium-manager Python packages to PyPI' +task :release_manager do |_task, arguments| + nightly = arguments.to_a.include?('nightly') + Rake::Task['py:check_credentials'].invoke(*arguments.to_a) + + if nightly + puts 'Updating selenium-manager version to nightly...' + old_version = manager_python_version + nightly_suffix = ".#{Time.now.strftime('%Y%m%d%H%M')}" + base = old_version.split('.')[0..2].join('.') + new_version = "#{base}#{nightly_suffix}" + Rake::Task['py:version_manager'].invoke(new_version) + ENV['TWINE_PASSWORD'] = ENV.fetch('TWINE_NIGHTLY_PASSWORD', nil) + end + + MANAGER_PYTHON_WHEEL_TARGETS.each do |target| + puts "Building: #{target}" + Bazel.execute('build', ['--config=release'], target) + end end desc 'Format Python code with ruff' From 1725e47d63bf467857aeff04566c42aaa8078f61 Mon Sep 17 00:00:00 2001 From: AutomatedTester Date: Fri, 22 May 2026 12:37:30 +0100 Subject: [PATCH 2/2] linting --- .../selenium_manager_linux_x86_64/__init__.py | 4 +- .../selenium_manager_macos/__init__.py | 4 +- .../selenium_manager_windows/__init__.py | 4 +- .../selenium_manager/__init__.py | 10 +---- rake_tasks/node.rake | 24 ++++++------ rake_tasks/python.rake | 38 ++++++++++--------- 6 files changed, 39 insertions(+), 45 deletions(-) diff --git a/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py b/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py index 160c82c177c2f..1c19e5054021e 100644 --- a/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py +++ b/py/selenium-manager-linux-x86-64/selenium_manager_linux_x86_64/__init__.py @@ -22,9 +22,7 @@ def main() -> None: - with importlib.resources.as_file( - importlib.resources.files(__package__) / "bin" / "selenium-manager" - ) as binary: + with importlib.resources.as_file(importlib.resources.files(__package__) / "bin" / "selenium-manager") as binary: os.chmod(binary, os.stat(binary).st_mode | 0o755) result = subprocess.run([str(binary)] + sys.argv[1:]) sys.exit(result.returncode) diff --git a/py/selenium-manager-macos/selenium_manager_macos/__init__.py b/py/selenium-manager-macos/selenium_manager_macos/__init__.py index 160c82c177c2f..1c19e5054021e 100644 --- a/py/selenium-manager-macos/selenium_manager_macos/__init__.py +++ b/py/selenium-manager-macos/selenium_manager_macos/__init__.py @@ -22,9 +22,7 @@ def main() -> None: - with importlib.resources.as_file( - importlib.resources.files(__package__) / "bin" / "selenium-manager" - ) as binary: + with importlib.resources.as_file(importlib.resources.files(__package__) / "bin" / "selenium-manager") as binary: os.chmod(binary, os.stat(binary).st_mode | 0o755) result = subprocess.run([str(binary)] + sys.argv[1:]) sys.exit(result.returncode) diff --git a/py/selenium-manager-windows/selenium_manager_windows/__init__.py b/py/selenium-manager-windows/selenium_manager_windows/__init__.py index e9c40f32ef69a..8bf19c8b76916 100644 --- a/py/selenium-manager-windows/selenium_manager_windows/__init__.py +++ b/py/selenium-manager-windows/selenium_manager_windows/__init__.py @@ -21,8 +21,6 @@ def main() -> None: - with importlib.resources.as_file( - importlib.resources.files(__package__) / "bin" / "selenium-manager.exe" - ) as binary: + with importlib.resources.as_file(importlib.resources.files(__package__) / "bin" / "selenium-manager.exe") as binary: result = subprocess.run([str(binary)] + sys.argv[1:]) sys.exit(result.returncode) diff --git a/py/selenium-manager/selenium_manager/__init__.py b/py/selenium-manager/selenium_manager/__init__.py index 0e4d8b23254e2..16f1c3ad8a465 100644 --- a/py/selenium-manager/selenium_manager/__init__.py +++ b/py/selenium-manager/selenium_manager/__init__.py @@ -28,18 +28,12 @@ def main() -> None: module_name = _PLATFORM_MODULES.get(sys.platform) if module_name is None: - raise SystemExit( - f"Unsupported platform: {sys.platform}. " - f"Supported: linux, darwin, win32" - ) + raise SystemExit(f"Unsupported platform: {sys.platform}. Supported: linux, darwin, win32") try: platform_module = importlib.import_module(module_name) except ImportError as exc: pkg_name = module_name.replace("_", "-") - raise SystemExit( - f"Platform package {pkg_name} is not installed.\n" - f"Run: pip install {pkg_name}" - ) from exc + raise SystemExit(f"Platform package {pkg_name} is not installed.\nRun: pip install {pkg_name}") from exc platform_module.main() diff --git a/rake_tasks/node.rake b/rake_tasks/node.rake index 4139cb553ec37..5e81b2b47e5c4 100644 --- a/rake_tasks/node.rake +++ b/rake_tasks/node.rake @@ -12,16 +12,18 @@ def manager_npm_version end end -MANAGER_NPM_FILES = %w[ - javascript/selenium-manager/package.json - javascript/selenium-manager/BUILD.bazel - javascript/selenium-manager-darwin/package.json - javascript/selenium-manager-darwin/BUILD.bazel - javascript/selenium-manager-linux-x64/package.json - javascript/selenium-manager-linux-x64/BUILD.bazel - javascript/selenium-manager-win32/package.json - javascript/selenium-manager-win32/BUILD.bazel -].freeze unless defined?(MANAGER_NPM_FILES) +unless defined?(MANAGER_NPM_FILES) + MANAGER_NPM_FILES = %w[ + javascript/selenium-manager/package.json + javascript/selenium-manager/BUILD.bazel + javascript/selenium-manager-darwin/package.json + javascript/selenium-manager-darwin/BUILD.bazel + javascript/selenium-manager-linux-x64/package.json + javascript/selenium-manager-linux-x64/BUILD.bazel + javascript/selenium-manager-win32/package.json + javascript/selenium-manager-win32/BUILD.bazel + ].freeze +end def setup_github_npm_auth token = ENV.fetch('GITHUB_TOKEN', nil) @@ -126,7 +128,7 @@ task :release_manager do |_task, arguments| '//javascript/selenium-manager-linux-x64:selenium-manager-linux-x64.publish', '//javascript/selenium-manager-darwin:selenium-manager-darwin.publish', '//javascript/selenium-manager-win32:selenium-manager-win32.publish', - '//javascript/selenium-manager:selenium-manager.publish', + '//javascript/selenium-manager:selenium-manager.publish' ] targets.each do |target| diff --git a/rake_tasks/python.rake b/rake_tasks/python.rake index f27cf9ce6fe47..dda059e7a83a4 100644 --- a/rake_tasks/python.rake +++ b/rake_tasks/python.rake @@ -14,23 +14,27 @@ def manager_python_version end end -MANAGER_PYTHON_FILES = %w[ - py/selenium-manager/pyproject.toml - py/selenium-manager/BUILD.bazel - py/selenium-manager-linux-x86-64/pyproject.toml - py/selenium-manager-linux-x86-64/BUILD.bazel - py/selenium-manager-macos/pyproject.toml - py/selenium-manager-macos/BUILD.bazel - py/selenium-manager-windows/pyproject.toml - py/selenium-manager-windows/BUILD.bazel -].freeze unless defined?(MANAGER_PYTHON_FILES) - -MANAGER_PYTHON_WHEEL_TARGETS = %w[ - //py/selenium-manager-linux-x86-64:selenium-manager-linux-x86-64-wheel - //py/selenium-manager-macos:selenium-manager-macos-wheel - //py/selenium-manager-windows:selenium-manager-windows-wheel - //py/selenium-manager:selenium-manager-wheel -].freeze unless defined?(MANAGER_PYTHON_WHEEL_TARGETS) +unless defined?(MANAGER_PYTHON_FILES) + MANAGER_PYTHON_FILES = %w[ + py/selenium-manager/pyproject.toml + py/selenium-manager/BUILD.bazel + py/selenium-manager-linux-x86-64/pyproject.toml + py/selenium-manager-linux-x86-64/BUILD.bazel + py/selenium-manager-macos/pyproject.toml + py/selenium-manager-macos/BUILD.bazel + py/selenium-manager-windows/pyproject.toml + py/selenium-manager-windows/BUILD.bazel + ].freeze +end + +unless defined?(MANAGER_PYTHON_WHEEL_TARGETS) + MANAGER_PYTHON_WHEEL_TARGETS = %w[ + //py/selenium-manager-linux-x86-64:selenium-manager-linux-x86-64-wheel + //py/selenium-manager-macos:selenium-manager-macos-wheel + //py/selenium-manager-windows:selenium-manager-windows-wheel + //py/selenium-manager:selenium-manager-wheel + ].freeze +end desc 'Build Python wheel and sdist with optional arguments' task :build do |_task, arguments|