Skip to content

Commit 11beda8

Browse files
authored
Replace urlretrieve with streaming download using urlopen (#384)
Updated setup.py to replace urllib.request.urlretrieve with a streaming download helper based on urlopen. This avoids the drawbacks of urlretrieve, such as lack of streaming support and limited control over requests. Using urlopen allows downloads to be written in chunks, reduces memory usage, and makes it easier to extend the logic with custom headers, retries, or checksum verification in the future. This improves the reliability and security of fetching dependency tarballs during the build process.
1 parent e24a84c commit 11beda8

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

.github/workflows/manylinux.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Build linux_x86_64 wheel
3333
env:
3434
PYXMLSEC_STATIC_DEPS: true
35-
PYXMLSEC_LIBXML2_VERSION: 2.14.6 # Lock it to libxml2 2.14.6 until the issue with 2.15.x is resolved; e.g. https://github.com/lsh123/xmlsec/issues/948
35+
PYXMLSEC_LIBXML2_VERSION: 2.14.6 # Lock it to libxml2 2.14.6 to match it with lxml
3636
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3737
run: |
3838
/opt/python/${{ matrix.python-abi }}/bin/python -m build

setup.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from distutils.version import StrictVersion as Version
1515
from pathlib import Path
1616
from urllib.parse import urljoin
17-
from urllib.request import Request, urlcleanup, urlopen, urlretrieve
17+
from urllib.request import Request, urlcleanup, urlopen
1818

1919
from setuptools import Extension, setup
2020
from setuptools.command.build_ext import build_ext as build_ext_orig
@@ -106,6 +106,16 @@ def latest_xmlsec_release():
106106
return tar_gz['browser_download_url']
107107

108108

109+
def download_lib(url, filename):
110+
req = Request(url, headers={'User-Agent': 'python-xmlsec build'})
111+
with urlopen(req) as r, open(filename, 'wb') as f:
112+
while True:
113+
chunk = r.read(8192)
114+
if not chunk:
115+
break
116+
f.write(chunk)
117+
118+
109119
class CrossCompileInfo:
110120
def __init__(self, host, arch, compiler):
111121
self.host = host
@@ -234,7 +244,7 @@ def prepare_static_build_win(self):
234244
else:
235245
self.info(f'Retrieving "{url}" to "{destfile}"')
236246
urlcleanup() # work around FTP bug 27973 in Py2.7.12+
237-
urlretrieve(url, str(destfile))
247+
download_lib(url, str(destfile))
238248

239249
for p in self.libs_dir.glob('*.zip'):
240250
with zipfile.ZipFile(str(p)) as f:
@@ -297,7 +307,7 @@ def prepare_static_build(self, build_platform):
297307
else:
298308
url = f'https://api.github.com/repos/openssl/openssl/tarball/openssl-{self.openssl_version}'
299309
self.info('{:10}: {} {}'.format('OpenSSL', 'version', self.openssl_version))
300-
urlretrieve(url, str(openssl_tar))
310+
download_lib(url, str(openssl_tar))
301311

302312
# fetch zlib
303313
zlib_tar = next(self.libs_dir.glob('zlib*.tar.gz'), None)
@@ -310,7 +320,7 @@ def prepare_static_build(self, build_platform):
310320
else:
311321
url = f'https://zlib.net/fossils/zlib-{self.zlib_version}.tar.gz'
312322
self.info('{:10}: {}'.format('zlib', f'PYXMLSEC_ZLIB_VERSION={self.zlib_version}, downloading from {url}'))
313-
urlretrieve(url, str(zlib_tar))
323+
download_lib(url, str(zlib_tar))
314324

315325
# fetch libiconv
316326
libiconv_tar = next(self.libs_dir.glob('libiconv*.tar.gz'), None)
@@ -319,13 +329,13 @@ def prepare_static_build(self, build_platform):
319329
libiconv_tar = self.libs_dir / 'libiconv.tar.gz'
320330
if self.libiconv_version is None:
321331
url = latest_libiconv_release()
322-
self.info('{:10}: {}'.format('zlib', f'PYXMLSEC_LIBICONV_VERSION unset, downloading latest from {url}'))
332+
self.info('{:10}: {}'.format('libiconv', f'PYXMLSEC_LIBICONV_VERSION unset, downloading latest from {url}'))
323333
else:
324334
url = f'https://ftp.gnu.org/pub/gnu/libiconv/libiconv-{self.libiconv_version}.tar.gz'
325335
self.info(
326-
'{:10}: {}'.format('zlib', f'PYXMLSEC_LIBICONV_VERSION={self.libiconv_version}, downloading from {url}')
336+
'{:10}: {}'.format('libiconv', f'PYXMLSEC_LIBICONV_VERSION={self.libiconv_version}, downloading from {url}')
327337
)
328-
urlretrieve(url, str(libiconv_tar))
338+
download_lib(url, str(libiconv_tar))
329339

330340
# fetch libxml2
331341
libxml2_tar = next(self.libs_dir.glob('libxml2*.tar.xz'), None)
@@ -341,7 +351,7 @@ def prepare_static_build(self, build_platform):
341351
'{:10}: {}'.format('libxml2', f'PYXMLSEC_LIBXML2_VERSION={self.libxml2_version}, downloading from {url}')
342352
)
343353
libxml2_tar = self.libs_dir / 'libxml2.tar.xz'
344-
urlretrieve(url, str(libxml2_tar))
354+
download_lib(url, str(libxml2_tar))
345355

346356
# fetch libxslt
347357
libxslt_tar = next(self.libs_dir.glob('libxslt*.tar.gz'), None)
@@ -357,7 +367,7 @@ def prepare_static_build(self, build_platform):
357367
'{:10}: {}'.format('libxslt', f'PYXMLSEC_LIBXSLT_VERSION={self.libxslt_version}, downloading from {url}')
358368
)
359369
libxslt_tar = self.libs_dir / 'libxslt.tar.gz'
360-
urlretrieve(url, str(libxslt_tar))
370+
download_lib(url, str(libxslt_tar))
361371

362372
# fetch xmlsec1
363373
xmlsec1_tar = next(self.libs_dir.glob('xmlsec1*.tar.gz'), None)
@@ -372,7 +382,7 @@ def prepare_static_build(self, build_platform):
372382
'{:10}: {}'.format('xmlsec1', f'PYXMLSEC_XMLSEC1_VERSION={self.xmlsec1_version}, downloading from {url}')
373383
)
374384
xmlsec1_tar = self.libs_dir / 'xmlsec1.tar.gz'
375-
urlretrieve(url, str(xmlsec1_tar))
385+
download_lib(url, str(xmlsec1_tar))
376386

377387
for file in (openssl_tar, zlib_tar, libiconv_tar, libxml2_tar, libxslt_tar, xmlsec1_tar):
378388
self.info(f'Unpacking {file.name}')

0 commit comments

Comments
 (0)