1{ lib
2, stdenv
3, buildPythonPackage
4, chromium
5, ffmpeg
6, firefox
7, git
8, greenlet
9, jq
10, nodejs
11, fetchFromGitHub
12, fetchurl
13, makeFontsConf
14, makeWrapper
15, pyee
16, python
17, pythonOlder
18, runCommand
19, setuptools-scm
20, unzip
21}:
22
23let
24 inherit (stdenv.hostPlatform) system;
25 throwSystem = throw "Unsupported system: ${system}";
26
27 driverVersion = "1.27.1";
28
29 driver = let
30 suffix = {
31 x86_64-linux = "linux";
32 aarch64-linux = "linux-arm64";
33 x86_64-darwin = "mac";
34 aarch64-darwin = "mac-arm64";
35 }.${system} or throwSystem;
36 filename = "playwright-${driverVersion}-${suffix}.zip";
37 in stdenv.mkDerivation {
38 pname = "playwright-driver";
39 version = driverVersion;
40
41 src = fetchurl {
42 url = "https://playwright.azureedge.net/builds/driver/${filename}";
43 sha256 = {
44 x86_64-linux = "0x71b4kb8hlyacixipgfbgjgrbmhckxpbmrs2xk8iis7n5kg7539";
45 aarch64-linux = "125lih7g2gj91k7j196wy5a5746wyfr8idj3ng369yh5wl7lfcfv";
46 x86_64-darwin = "0z2kww4iby1izkwn6z2ai94y87bkjvwak8awdmjm8sgg00pa9l1a";
47 aarch64-darwin = "0qajh4ac5lr1sznb2c471r5c5g2r0dk2pyqz8vhvnbk36r524h1h";
48 }.${system} or throwSystem;
49 };
50
51 sourceRoot = ".";
52
53 nativeBuildInputs = [ unzip ];
54
55 postPatch = ''
56 # Use Nix's NodeJS instead of the bundled one.
57 substituteInPlace playwright.sh --replace '"$SCRIPT_PATH/node"' '"${nodejs}/bin/node"'
58 rm node
59
60 # Hard-code the script path to $out directory to avoid a dependency on coreutils
61 substituteInPlace playwright.sh \
62 --replace 'SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)"' "SCRIPT_PATH=$out"
63
64 patchShebangs playwright.sh package/bin/*.sh
65 '';
66
67 installPhase = ''
68 runHook preInstall
69
70 mkdir -p $out/bin
71 mv playwright.sh $out/bin/playwright
72 mv package $out/
73
74 runHook postInstall
75 '';
76
77 passthru = {
78 inherit filename;
79 };
80 };
81
82 browsers-mac = stdenv.mkDerivation {
83 pname = "playwright-browsers";
84 version = driverVersion;
85
86 src = runCommand "playwright-browsers-base" {
87 outputHashMode = "recursive";
88 outputHashAlgo = "sha256";
89 outputHash = {
90 x86_64-darwin = "0z2kww4iby1izkwn6z2ai94y87bkjvwak8awdmjm8sgg00pa9l1a";
91 }.${system} or throwSystem;
92 } ''
93 export PLAYWRIGHT_BROWSERS_PATH=$out
94 ${driver}/bin/playwright install
95 rm -r $out/.links
96 '';
97
98 installPhase = ''
99 mkdir $out
100 cp -r * $out/
101 '';
102 };
103
104 browsers-linux = { withFirefox ? true, withChromium ? true }: let
105 fontconfig = makeFontsConf {
106 fontDirectories = [];
107 };
108 in runCommand ("playwright-browsers"
109 + lib.optionalString (withFirefox && !withChromium) "-firefox"
110 + lib.optionalString (!withFirefox && withChromium) "-chromium")
111 {
112 nativeBuildInputs = [
113 makeWrapper
114 jq
115 ];
116 } (''
117 BROWSERS_JSON=${driver}/package/browsers.json
118 '' + lib.optionalString withChromium ''
119 CHROMIUM_REVISION=$(jq -r '.browsers[] | select(.name == "chromium").revision' $BROWSERS_JSON)
120 mkdir -p $out/chromium-$CHROMIUM_REVISION/chrome-linux
121
122 # See here for the Chrome options:
123 # https://github.com/NixOS/nixpkgs/issues/136207#issuecomment-908637738
124 makeWrapper ${chromium}/bin/chromium $out/chromium-$CHROMIUM_REVISION/chrome-linux/chrome \
125 --set SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt \
126 --set FONTCONFIG_FILE ${fontconfig}
127 '' + lib.optionalString withFirefox ''
128 FIREFOX_REVISION=$(jq -r '.browsers[] | select(.name == "firefox").revision' $BROWSERS_JSON)
129 mkdir -p $out/firefox-$FIREFOX_REVISION/firefox
130 ln -s ${firefox}/bin/firefox $out/firefox-$FIREFOX_REVISION/firefox/firefox
131 '' + ''
132 FFMPEG_REVISION=$(jq -r '.browsers[] | select(.name == "ffmpeg").revision' $BROWSERS_JSON)
133 mkdir -p $out/ffmpeg-$FFMPEG_REVISION
134 ln -s ${ffmpeg}/bin/ffmpeg $out/ffmpeg-$FFMPEG_REVISION/ffmpeg-linux
135 '');
136in
137buildPythonPackage rec {
138 pname = "playwright";
139 version = "1.27.1";
140 format = "setuptools";
141 disabled = pythonOlder "3.7";
142
143 src = fetchFromGitHub {
144 owner = "microsoft";
145 repo = "playwright-python";
146 rev = "v${version}";
147 sha256 = "sha256-cI/4GdkmTikoP9O0Skh/0jCxxRypRua0231iKcxtBcY=";
148 };
149
150 patches = [
151 # This patches two things:
152 # - The driver location, which is now a static package in the Nix store.
153 # - The setup script, which would try to download the driver package from
154 # a CDN and patch wheels so that they include it. We don't want this
155 # we have our own driver build.
156 ./driver-location.patch
157 ];
158
159 postPatch = ''
160 # if setuptools_scm is not listing files via git almost all python files are excluded
161 export HOME=$(mktemp -d)
162 git init .
163 git add -A .
164 git config --global user.email "nixpkgs"
165 git config --global user.name "nixpkgs"
166 git commit -m "workaround setuptools-scm"
167
168 substituteInPlace setup.py \
169 --replace "greenlet==1.1.3" "greenlet>=1.1.3" \
170 --replace "pyee==8.1.0" "pyee>=8.1.0" \
171 --replace "setuptools-scm==7.0.5" "setuptools-scm>=7.0.5" \
172 --replace "wheel==0.37.1" "wheel>=0.37.1"
173
174 # Skip trying to download and extract the driver.
175 # This is done manually in postInstall instead.
176 substituteInPlace setup.py \
177 --replace "self._download_and_extract_local_driver(base_wheel_bundles)" ""
178
179 # Set the correct driver path with the help of a patch in patches
180 substituteInPlace playwright/_impl/_driver.py \
181 --replace "@driver@" "${driver}/bin/playwright"
182 '';
183
184
185 nativeBuildInputs = [ git setuptools-scm ];
186
187 propagatedBuildInputs = [
188 greenlet
189 pyee
190 ];
191
192 postInstall = ''
193 ln -s ${driver} $out/${python.sitePackages}/playwright/driver
194 '';
195
196 # Skip tests because they require network access.
197 doCheck = false;
198
199 pythonImportsCheck = [
200 "playwright"
201 ];
202
203 passthru = rec {
204 inherit driver;
205 browsers = {
206 x86_64-linux = browsers-linux { };
207 aarch64-linux = browsers-linux { };
208 x86_64-darwin = browsers-mac;
209 aarch64-darwin = browsers-mac;
210 }.${system} or throwSystem;
211 browsers-chromium = browsers-linux { withFirefox = false; };
212 browsers-firefox = browsers-linux { withChromium = false; };
213
214 tests = {
215 inherit driver browsers;
216 };
217 };
218
219 meta = with lib; {
220 description = "Python version of the Playwright testing and automation library";
221 homepage = "https://github.com/microsoft/playwright-python";
222 license = licenses.asl20;
223 maintainers = with maintainers; [ techknowlogick yrd SuperSandro2000 ];
224 };
225}