1+ import com.google.gson.JsonParser
12import java.net.URI
3+ import java.net.http.HttpClient
4+ import java.net.http.HttpRequest
5+ import java.net.http.HttpResponse
26import java.util.zip.ZipFile
7+ import kotlin.time.Duration.Companion.minutes
8+ import kotlin.time.toJavaDuration
39
4- val CT2_URL = " https://nightly.link/OpenNMT/CTranslate2/workflows/ci/master/python-wheels-{dist}-{arch}.zip "
10+ val CT2_INDEX = " https://pypi.org/simple/ctranslate2/ "
511val ct2Version = rootProject.property(" ct2_version" )!! as String
612
713data class RustPlatform (
@@ -10,7 +16,8 @@ data class RustPlatform(
1016 val architecture : String ,
1117 val exportedFiles : List <String >
1218) {
13- val ct2Name = " ${if (systemName == " osx" ) " macos" else systemName} -${if (architecture == " amd64" ) " auto64" else if (systemName == " osx" ) " arm64" else " aarch64" } "
19+ val ct2Name =
20+ " ${if (systemName == " osx" ) " macos" else systemName} -${if (architecture == " amd64" ) " auto64" else if (systemName == " osx" ) " arm64" else " aarch64" } "
1421
1522 fun isHost (): Boolean {
1623 val hostOs = System .getProperty(" os.name" ).lowercase()
@@ -38,7 +45,9 @@ open class ExecutableTask @Inject constructor(@Internal val execOperations: Exec
3845
3946data class Platform (
4047 val distribution : String ,
41- val architecture : String
48+ val architecture : String ,
49+ val outputDist : String ,
50+ val outputArch : String
4251)
4352
4453interface FileMatcher {
@@ -62,23 +71,27 @@ class RegexBased(val regex: Regex, override val fileName: String) : FileMatcher
6271// These files provide Python wheels, but we can technically access any one of them. We're looking for these
6372// files in those wheels specifically.
6473val ct2Files = mapOf (
65- Platform (" Windows" , " auto64" ) to listOf (
74+ Platform (" win " , " amd64 " , " Windows" , " auto64" ) to listOf (
6675 StringBased (" ctranslate2/ctranslate2.dll" , " ctranslate2.dll" ),
6776 StringBased (" ctranslate2/cudnn64_9.dll" , " cudnn64_9.dll" ),
6877 StringBased (" ctranslate2/libiomp5md.dll" , " libiomp5md.dll" )
6978 ),
70- /* Platform("macOS", "arm64") to listOf(
79+ Platform (" macosx_10_13" , " x86_64" , " macOS" , " x86_64" ) to listOf (
80+ RegexBased (Regex (" ctranslate2/\\ .dylibs/libctranslate2\\ .\\ d\\ .\\ d\\ .\\ d\\ .dylib" ), " libctranslate2.dylib" ),
81+ RegexBased (Regex (" ctranslate2/\\ .dylibs/libiomp5\\ .dylib" ), " libiomp5.dylib" )
82+ ),
83+ Platform (" macosx_11_0" , " arm64" , " macOS" , " arm64" ) to listOf (
7184 RegexBased (Regex (" ctranslate2/\\ .dylibs/libctranslate2\\ .\\ d\\ .\\ d\\ .\\ d\\ .dylib" ), " libctranslate2.dylib" )
72- ),*/
73- Platform (" Linux" , " auto64" ) to listOf (
85+ ),
86+ Platform (" manylinux_2_17 " , " x86_64.manylinux2014_x86_64 " , " Linux" , " auto64" ) to listOf (
7487 RegexBased (Regex (" ctranslate2\\ .libs/libctranslate2-\\ w+\\ .so\\ .\\ d\\ .\\ d\\ .\\ d" ), " libctranslate2.so" ),
7588 RegexBased (Regex (" ctranslate2\\ .libs/libcudnn-\\ w+\\ .so\\ .\\ d\\ .\\ d\\ .\\ d" ), " libcudnn.so" ),
7689 RegexBased (Regex (" ctranslate2\\ .libs/libgomp-\\ w+\\ .so\\ .\\ d\\ .\\ d\\ .\\ d" ), " libgomp.so" ),
7790 ),
78- /* Platform("Linux", "aarch64") to listOf(
91+ Platform (" manylinux_2_17 " , " aarch64.manylinux2014_aarch64 " , " Linux" , " aarch64" ) to listOf (
7992 RegexBased (Regex (" ctranslate2\\ .libs/libctranslate2-\\ w+\\ .so\\ .\\ d\\ .\\ d\\ .\\ d" ), " libctranslate2.so" ),
8093 RegexBased (Regex (" ctranslate2\\ .libs/libgomp-\\ w+\\ .so\\ .\\ d\\ .\\ d\\ .\\ d" ), " libgomp.so" ),
81- )*/
94+ )
8295)
8396
8497tasks {
@@ -92,9 +105,25 @@ tasks {
92105 if (! versionedDir.asFile.exists())
93106 versionedDir.asFile.mkdirs()
94107
108+ val client = HttpClient .newBuilder()
109+ .connectTimeout(5 .minutes.toJavaDuration())
110+ .build()
111+ val request = HttpRequest .newBuilder(URI .create(CT2_INDEX ))
112+ .GET ()
113+ .header(" Accept" , " application/vnd.pypi.simple.v1+json" )
114+ .build()
115+
116+ val response = client.send(request, HttpResponse .BodyHandlers .ofString())
117+ val json = JsonParser .parseString(response.body())
118+ .asJsonObject
119+ .getAsJsonArray(" files" )
120+
121+ client.close()
122+
95123 for ((platform, fileMatchers) in ct2Files) {
96- val platformDir = versionedDir.dir(" ${platform.distribution} -${platform.architecture} " .lowercase())
97- val file = versionedDir.file(" python-wheels-${platform.distribution} -${platform.architecture} .zip" ).asFile
124+ val platformDir = versionedDir.dir(" ${platform.outputDist} -${platform.outputArch} " .lowercase())
125+ val file =
126+ versionedDir.file(" ctranslate2-${ct2Version} -cp39-cp39-${platform.distribution} _${platform.architecture} .whl" ).asFile
98127
99128 if (file.exists())
100129 continue
@@ -104,9 +133,15 @@ tasks {
104133 if (! platformDir.asFile.exists())
105134 platformDir.asFile.mkdirs()
106135
107- val url = URI .create(CT2_URL .replace(" {dist}" , platform.distribution).replace(" {arch}" , platform.architecture)).toURL()
136+ val url = URI .create(
137+ json.first {
138+ it.asJsonObject.get(" filename" ).asString == " ctranslate2-${ct2Version} -cp39-cp39-${platform.distribution} _${platform.architecture} .whl"
139+ }
140+ .asJsonObject.get(" url" ).asString
141+ )
142+ .toURL()
108143
109- logger.info(" Downloading CTranslate2 wheels for ${platform.distribution } (${platform.architecture } )..." )
144+ logger.info(" Downloading CTranslate2 wheels for ${platform.outputDist } (${platform.outputArch } )..." )
110145 file.outputStream().use { f ->
111146 url.openStream().use {
112147 it.transferTo(f)
@@ -115,26 +150,7 @@ tasks {
115150
116151 logger.info(" Finished downloading! Getting required files..." )
117152
118- lateinit var wheel: File
119- val zip = ZipFile (file)
120- for (entry in zip.entries()) {
121- if (entry.name.endsWith(" .whl" )) {
122- wheel = versionedDir.file(entry.name).asFile
123-
124- if (! wheel.exists()) {
125- wheel.createNewFile()
126- zip.getInputStream(entry).use {
127- wheel.outputStream().use { f ->
128- it.transferTo(f)
129- }
130- }
131- }
132-
133- break
134- }
135- }
136-
137- val wheelZip = ZipFile (wheel)
153+ val wheelZip = ZipFile (file)
138154 for (entry in wheelZip.entries()) {
139155 val matchedFile = fileMatchers.firstOrNull { it.match(entry.name) } ? : continue
140156 val filePath = platformDir.file(matchedFile.fileName).asFile
0 commit comments