1414
1515import glob
1616import os
17+ import platform
1718import shutil
1819import subprocess
1920import sys
2021import zipfile
2122from pathlib import Path
23+ from typing import Dict , List
2224
2325from setuptools import find_packages , setup
2426
@@ -40,6 +42,23 @@ def extractall(zip: zipfile.ZipFile, path: str) -> None:
4042 os .chmod (extracted_path , attr )
4143
4244
45+ def download_driver (zip_name : str ) -> None :
46+ zip_file = f"playwright-{ driver_version } -{ zip_name } .zip"
47+ if os .path .exists ("driver/" + zip_file ):
48+ return
49+ url = "https://playwright.azureedge.net/builds/driver/"
50+ if (
51+ "-alpha" in driver_version
52+ or "-beta" in driver_version
53+ or "-next" in driver_version
54+ ):
55+ url = url + "next/"
56+ url = url + zip_file
57+ print (f"Fetching { url } " )
58+ # Don't replace this with urllib - Python won't have certificates to do SSL on all platforms.
59+ subprocess .check_call (["curl" , url , "-o" , "driver/" + zip_file ])
60+
61+
4362class PlaywrightBDistWheelCommand (BDistWheelCommand ):
4463 user_options = BDistWheelCommand .user_options + [
4564 ("all" , "a" , "create wheels for all platforms" )
@@ -57,90 +76,90 @@ def run(self) -> None:
5776 super ().run ()
5877 os .makedirs ("driver" , exist_ok = True )
5978 os .makedirs ("playwright/driver" , exist_ok = True )
60- if self .all :
61- # If building for all platforms
62- platform_map = {
63- "darwin" : [
64- {
65- "zip_name" : "mac" ,
66- "wheels" : [
67- "macosx_10_13_x86_64.whl" ,
68- "macosx_11_0_universal2.whl" ,
69- ],
70- },
71- {
72- "zip_name" : "mac-arm64" ,
73- "wheels" : [
74- "macosx_11_0_arm64.whl" ,
75- ],
76- },
77- ],
78- "linux" : [
79- {"zip_name" : "linux" , "wheels" : ["manylinux1_x86_64.whl" ]},
80- {
81- "zip_name" : "linux-arm64" ,
82- "wheels" : ["manylinux_2_17_aarch64.manylinux2014_aarch64.whl" ],
83- },
84- ],
85- "win32" : [
86- {
87- "zip_name" : "win32_x64" ,
88- "wheels" : ["win32.whl" , "win_amd64.whl" ],
89- }
90- ],
91- }
92- platforms = [* platform_map .values ()]
93- else :
94- # If building for only current platform
95- platform_map = {
96- "darwin" : [
97- {
98- "zip_name" : "mac" ,
99- "wheels" : ["macosx_10_13_x86_64.whl" ],
100- },
101- ],
102- "linux" : [{"zip_name" : "linux" , "wheels" : ["manylinux1_x86_64.whl" ]}],
103- "win32" : [
104- {
105- "zip_name" : "win32_x64" ,
106- "wheels" : ["win_amd64.whl" ],
107- }
108- ],
109- }
110- platforms = [platform_map [sys .platform ]]
111- for platform in platforms :
112- for arch in platform :
113- zip_file = f"playwright-{ driver_version } -{ arch ['zip_name' ]} .zip"
114- if not os .path .exists ("driver/" + zip_file ):
115- url = f"https://playwright.azureedge.net/builds/driver/{ zip_file } "
116- print (f"Fetching { url } " )
117- # Don't replace this with urllib - Python won't have certificates to do SSL on all platforms.
118- subprocess .check_call (["curl" , url , "-o" , "driver/" + zip_file ])
119- base_wheel_location = glob .glob (os .path .join (self .dist_dir , "*.whl" ))[0 ]
120- without_platform = base_wheel_location [:- 7 ]
79+ base_wheel_bundles : List [Dict [str , str ]] = [
80+ {
81+ "wheel" : "macosx_10_13_x86_64.whl" ,
82+ "machine" : "x86_64" ,
83+ "platform" : "darwin" ,
84+ "zip_name" : "mac" ,
85+ },
86+ {
87+ "wheel" : "macosx_11_0_universal2.whl" ,
88+ "machine" : "x86_64" ,
89+ "platform" : "darwin" ,
90+ "zip_name" : "mac" ,
91+ },
92+ {
93+ "wheel" : "macosx_11_0_arm64.whl" ,
94+ "machine" : "arm64" ,
95+ "platform" : "darwin" ,
96+ "zip_name" : "mac-arm64" ,
97+ },
98+ {
99+ "wheel" : "manylinux1_x86_64.whl" ,
100+ "machine" : "x86_64" ,
101+ "platform" : "linux" ,
102+ "zip_name" : "linux" ,
103+ },
104+ {
105+ "wheel" : "manylinux_2_17_aarch64.manylinux2014_aarch64.whl" ,
106+ "machine" : "aarch64" ,
107+ "platform" : "linux" ,
108+ "zip_name" : "linux-arm64" ,
109+ },
110+ {
111+ "wheel" : "win32.whl" ,
112+ "machine" : "i386" ,
113+ "platform" : "win32" ,
114+ "zip_name" : "win32_x64" ,
115+ },
116+ {
117+ "wheel" : "win_amd64.whl" ,
118+ "machine" : "amd64" ,
119+ "platform" : "win32" ,
120+ "zip_name" : "win32_x64" ,
121+ },
122+ ]
123+ self ._download_and_extract_local_driver (base_wheel_bundles )
121124
122- for platform in platforms :
123- for arch in platform :
124- zip_file = f"driver/playwright-{ driver_version } -{ arch ['zip_name' ]} .zip"
125- with zipfile .ZipFile (zip_file , "r" ) as zip :
126- extractall (zip , f"driver/{ arch ['zip_name' ]} " )
127- if platform_map [sys .platform ][0 ] in platform :
128- with zipfile .ZipFile (zip_file , "r" ) as zip :
129- extractall (zip , "playwright/driver" )
130- for wheel in arch ["wheels" ]:
131- wheel_location = without_platform + wheel
132- shutil .copy (base_wheel_location , wheel_location )
133- with zipfile .ZipFile (wheel_location , "a" ) as zip :
134- driver_root = os .path .abspath (f"driver/{ arch ['zip_name' ]} " )
135- for dir_path , _ , files in os .walk (driver_root ):
136- for file in files :
137- from_path = os .path .join (dir_path , file )
138- to_path = os .path .relpath (from_path , driver_root )
139- zip .write (from_path , f"playwright/driver/{ to_path } " )
140- zip .writestr (
141- "playwright/driver/README.md" , f"{ wheel } driver package"
142- )
125+ wheels = base_wheel_bundles
126+ if not self .all :
127+ # Limit to 1, since for MacOS e.g. we have multiple wheels for the same platform and architecture and Conda expects 1.
128+ wheels = list (
129+ filter (
130+ lambda wheel : wheel ["platform" ] == sys .platform
131+ and wheel ["machine" ] == platform .machine ().lower (),
132+ base_wheel_bundles ,
133+ )
134+ )[:1 ]
135+ self ._build_wheels (wheels )
143136
137+ def _build_wheels (
138+ self ,
139+ wheels : List [Dict [str , str ]],
140+ ) -> None :
141+ base_wheel_location : str = glob .glob (os .path .join (self .dist_dir , "*.whl" ))[0 ]
142+ without_platform = base_wheel_location [:- 7 ]
143+ for wheel_bundle in wheels :
144+ download_driver (wheel_bundle ["zip_name" ])
145+ zip_file = (
146+ f"driver/playwright-{ driver_version } -{ wheel_bundle ['zip_name' ]} .zip"
147+ )
148+ with zipfile .ZipFile (zip_file , "r" ) as zip :
149+ extractall (zip , f"driver/{ wheel_bundle ['zip_name' ]} " )
150+ wheel_location = without_platform + wheel_bundle ["wheel" ]
151+ shutil .copy (base_wheel_location , wheel_location )
152+ with zipfile .ZipFile (wheel_location , "a" ) as zip :
153+ driver_root = os .path .abspath (f"driver/{ wheel_bundle ['zip_name' ]} " )
154+ for dir_path , _ , files in os .walk (driver_root ):
155+ for file in files :
156+ from_path = os .path .join (dir_path , file )
157+ to_path = os .path .relpath (from_path , driver_root )
158+ zip .write (from_path , f"playwright/driver/{ to_path } " )
159+ zip .writestr (
160+ "playwright/driver/README.md" ,
161+ f"{ wheel_bundle ['wheel' ]} driver package" ,
162+ )
144163 os .remove (base_wheel_location )
145164 if InWheel :
146165 for whlfile in glob .glob (os .path .join (self .dist_dir , "*.whl" )):
@@ -156,6 +175,27 @@ def run(self) -> None:
156175 else :
157176 print ("auditwheel not installed, not updating RECORD file" )
158177
178+ def _download_and_extract_local_driver (
179+ self ,
180+ wheels : List [Dict [str , str ]],
181+ ) -> None :
182+ zip_names_for_current_system = set (
183+ map (
184+ lambda wheel : wheel ["zip_name" ],
185+ filter (
186+ lambda wheel : wheel ["machine" ] == platform .machine ().lower ()
187+ and wheel ["platform" ] == sys .platform ,
188+ wheels ,
189+ ),
190+ )
191+ )
192+ assert len (zip_names_for_current_system ) == 1
193+ zip_name = zip_names_for_current_system .pop ()
194+ download_driver (zip_name )
195+ zip_file = f"driver/playwright-{ driver_version } -{ zip_name } .zip"
196+ with zipfile .ZipFile (zip_file , "r" ) as zip :
197+ extractall (zip , "playwright/driver" )
198+
159199
160200setup (
161201 name = "playwright" ,
0 commit comments