From 67a6899f62d4ad1ffaa852155938aee201b2fb41 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Thu, 3 Nov 2022 14:39:46 -0700 Subject: [PATCH 1/6] Add CI for testing the built wheels --- .github/workflows/test.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 420d116..bdd3555 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,7 +23,6 @@ jobs: pip install -r requirements.txt - name: Build Wheels run: | - mkdir dist python make_wheels.py - name: Show built files run: | From f80ece7ad0b0dbf1c5b7b6eb125d8e57a5dd1f6b Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Thu, 3 Nov 2022 13:48:51 -0700 Subject: [PATCH 2/6] Add initial support for downloading musl-built nodejs from the unofficial builds --- .github/workflows/test.yaml | 1 + .gitignore | 6 +++++- make_wheels.py | 33 +++++++++++++++++++++++++++------ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bdd3555..420d116 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,6 +23,7 @@ jobs: pip install -r requirements.txt - name: Build Wheels run: | + mkdir dist python make_wheels.py - name: Show built files run: | diff --git a/.gitignore b/.gitignore index d23485d..a46a752 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ nodejs-cmd/*.egg-info .DS_Store env*/ __pycache__/ -*.py[cod] \ No newline at end of file +*.py[cod] +venv +package.json +node_modules +package-lock.json diff --git a/make_wheels.py b/make_wheels.py index ed21e0d..c48dec7 100644 --- a/make_wheels.py +++ b/make_wheels.py @@ -1,5 +1,6 @@ import os import hashlib +import pathlib import urllib.request import libarchive from email.message import EmailMessage @@ -45,8 +46,17 @@ 'linux-x64': 'manylinux_2_12_x86_64.manylinux2010_x86_64', 'linux-armv7l': 'manylinux_2_17_armv7l.manylinux2014_armv7l', 'linux-arm64': 'manylinux_2_17_aarch64.manylinux2014_aarch64', + 'linux-x64-musl': 'musllinux_1_1_x86_64' } +# https://github.com/nodejs/unofficial-builds/ +# Versions added here should match the keys above +UNOFFICIAL_NODEJS_BUILDS = {'linux-x64-musl'} + +_mismatched_versions = UNOFFICIAL_NODEJS_BUILDS - set(PLATFORMS.keys()) +if _mismatched_versions: + raise Exception(f"A version mismatch occurred. Check the usage of {_mismatched_versions}") + class ReproducibleWheelFile(WheelFile): def writestr(self, zinfo, *args, **kwargs): @@ -113,6 +123,11 @@ def write_nodejs_wheel(out_dir, *, node_version, version, platform, archive): entry_points = {} init_imports = [] + # Create the output directory if it does not exist + out_dir_path = pathlib.Path(out_dir) + if not out_dir_path.exists(): + out_dir_path.mkdir(parents=True) + with libarchive.memory_reader(archive) as archive: for entry in archive: entry_name = '/'.join(entry.name.split('/')[1:]) @@ -246,13 +261,16 @@ def main() -> None: """).encode('ascii') contents['nodejs/__init__.py'] = (cleandoc(""" + import sys from .node import path as path, main as main, call as call, run as run, Popen as Popen - {init_imports} + if not '-m' in sys.argv: + {init_imports} __version__ = "{version}" node_version = "{node_version}" """)).format( - init_imports='\n'.join(init_imports), + # Note: two space indentation above and below is necessary to align + init_imports='\n '.join(init_imports), version=version, node_version=node_version, ).encode('ascii') @@ -294,10 +312,13 @@ def make_nodejs_version(node_version, suffix=''): print('Suffix:', suffix) for node_platform, python_platform in PLATFORMS.items(): - print(f'- Making Wheel for {node_platform}') - node_url = f'https://nodejs.org/dist/v{node_version}/node-v{node_version}-{node_platform}.' + \ - ('zip' if node_platform.startswith('win-') else 'tar.xz') - + filetype = 'zip' if node_platform.startswith('win-') else 'tar.xz' + if node_platform in UNOFFICIAL_NODEJS_BUILDS: + node_url = f'https://unofficial-builds.nodejs.org/download/release/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' + else: + node_url = f'https://nodejs.org/dist/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' + + print(f'- Making Wheel for {node_platform} from {node_url}') try: with urllib.request.urlopen(node_url) as request: node_archive = request.read() From 4a14205617cf50c334aae0656463d5a987b380b9 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Thu, 3 Nov 2022 14:55:24 -0700 Subject: [PATCH 3/6] Throw an error if any warnings are emitted when invoking our own package --- .github/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 420d116..2e319d7 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -77,7 +77,7 @@ jobs: pip install dist\nodejs_bin-${{matrix.nodejs-version}}a3-py3-none-win_amd64.whl - name: Test Package run: - python -m nodejs --version - python -m nodejs.npm --version + python -W error -m nodejs --version + python -W error -m nodejs.npm --version From 2248ea2053a8d471bb9aae5d0859939d17590c14 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Thu, 3 Nov 2022 15:36:34 -0700 Subject: [PATCH 4/6] Add testing for variations of operating systems in docker --- .dockerignore | 2 ++ .github/workflows/test.yaml | 41 +++++++++++++++++++++++++++++++++++-- Dockerfile | 26 +++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0d0d4f0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +* +!dist diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2e319d7..7de1123 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - nodejs-version: ['16.15.1', '14.19.3', '18.4.0'] + nodejs-version: ['14.19.3', '16.15.1', '18.4.0'] python-version: ['3.7', '3.8', '3.9', '3.10'] steps: @@ -79,5 +79,42 @@ jobs: run: python -W error -m nodejs --version python -W error -m nodejs.npm --version + test-docker: + name: "Test Docker OS:${{ matrix.os-variant }} Python:${{ matrix.python-version }} NodeJS:${{ matrix.nodejs-version }}" + runs-on: ubuntu-latest + needs: [build-wheels] + strategy: + fail-fast: false + matrix: + os-variant: [alpine, slim-buster, slim-bullseye] + python-version: ['3.7', '3.8', '3.9', '3.10'] + nodejs-version: ['14.19.3', '16.15.1', '18.4.0'] - + steps: + - uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: arm64 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + - uses: actions/download-artifact@v3 + with: + name: nodejs-pip-wheels + path: dist + - name: Docker build + run: | + if [[ ${{ matrix.os-variant }} =~ "alpine" ]]; then + WHEEL_TO_INSTALL=nodejs_bin-${{ matrix.nodejs-version }}a3-py3-none-musllinux_1_1_x86_64.whl + else + WHEEL_TO_INSTALL=nodejs_bin-${{ matrix.nodejs-version }}a3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl + fi + echo "WHEEL_TO_INSTALL=${WHEEL_TO_INSTALL}" + docker build \ + -f Dockerfile \ + --build-arg PYTHON_VERSION=${{ matrix.python-version }} \ + --build-arg OS_VARIANT=${{ matrix.os-variant }} \ + --build-arg WHEEL_TO_INSTALL=${WHEEL_TO_INSTALL} \ + . diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..97f7286 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +ARG PYTHON_VERSION=3.10 +ARG OS_VARIANT=bullseye-slim + +FROM python:${PYTHON_VERSION}-${OS_VARIANT} + +ARG PYTHON_VERSION +ENV PYTHON_VERSION=${PYTHON_VERSION} +ARG OS_VARIANT +ENV OS_VARIANT=${OS_VARIANT} + +# This is required should be supplied as a build-arg +ARG WHEEL_TO_INSTALL +RUN test -n "${WHEEL_TO_INSTALL}" || (echo "Must supply WHEEL_TO_INSTALL as build arg"; exit 1) + +COPY dist/${WHEEL_TO_INSTALL} dist/${WHEEL_TO_INSTALL} + +# NodeJS needs libstdc++ to be present +# https://github.com/nodejs/unofficial-builds/#builds +RUN if echo "${OS_VARIANT}" | grep -e "alpine"; then \ + apk add libstdc++; \ + fi + +RUN pip install dist/${WHEEL_TO_INSTALL} + +RUN python -m nodejs --version +RUN python -m nodejs.npm --version From 3c9679b79196d5621c6b81b70ebbdcfcc3243e86 Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Thu, 3 Nov 2022 23:14:05 -0700 Subject: [PATCH 5/6] Add support for testing arm64 variants --- .github/workflows/test.yaml | 60 ++++++++++++++++++++++----- make_wheels.py | 81 ++++++++++++++++++++++++++++--------- 2 files changed, 113 insertions(+), 28 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7de1123..b11f10b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,6 +14,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: arm64 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true - uses: actions/setup-python@v4 with: python-version: "3.10" @@ -23,7 +31,6 @@ jobs: pip install -r requirements.txt - name: Build Wheels run: | - mkdir dist python make_wheels.py - name: Show built files run: | @@ -31,7 +38,7 @@ jobs: - uses: actions/upload-artifact@v3 with: name: nodejs-pip-wheels - path: dist/ + path: dist if-no-files-found: error retention-days: 1 @@ -42,7 +49,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [windows-latest, macos-latest] nodejs-version: ['14.19.3', '16.15.1', '18.4.0'] python-version: ['3.7', '3.8', '3.9', '3.10'] @@ -79,14 +86,16 @@ jobs: run: python -W error -m nodejs --version python -W error -m nodejs.npm --version + test-docker: - name: "Test Docker OS:${{ matrix.os-variant }} Python:${{ matrix.python-version }} NodeJS:${{ matrix.nodejs-version }}" + name: "Test Docker Architecture:${{ matrix.cpu-arch }} OS:${{ matrix.os-variant }} Python:${{ matrix.python-version }} NodeJS:${{ matrix.nodejs-version }}" runs-on: ubuntu-latest needs: [build-wheels] strategy: fail-fast: false matrix: os-variant: [alpine, slim-buster, slim-bullseye] + cpu-arch: [linux/amd64, linux/arm64] python-version: ['3.7', '3.8', '3.9', '3.10'] nodejs-version: ['14.19.3', '16.15.1', '18.4.0'] @@ -104,16 +113,49 @@ jobs: with: name: nodejs-pip-wheels path: dist + - name: List available wheels + run: | + ls -lah dist - name: Docker build run: | - if [[ ${{ matrix.os-variant }} =~ "alpine" ]]; then - WHEEL_TO_INSTALL=nodejs_bin-${{ matrix.nodejs-version }}a3-py3-none-musllinux_1_1_x86_64.whl - else - WHEEL_TO_INSTALL=nodejs_bin-${{ matrix.nodejs-version }}a3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl - fi + wheel_prefix_except_platform=nodejs_bin-${{ matrix.nodejs-version }}a3-py3-none + + case ${{ matrix.cpu-arch }} in + linux/amd64) + python_cpu_arch=x86_64 + python_libc_variant=2_12 + manylinx_variant_year=2010 + ;; + linux/arm64) + python_cpu_arch=aarch64 + python_libc_variant=2_17 + manylinx_variant_year=2014 + ;; + *) + echo "Could not parse the CPU architecture" + exit 1 + ;; + esac + + case ${{ matrix.os-variant }} in + alpine) + python_platform=musllinux_1_1_${python_cpu_arch} + ;; + slim-buster | slim-bullseye) + python_platform=manylinux_${python_libc_variant}_${python_cpu_arch}.manylinux${manylinx_variant_year}_${python_cpu_arch} + ;; + *) + echo "Could not parse the OS variant" + exit 1 + ;; + esac + + WHEEL_TO_INSTALL=${wheel_prefix_except_platform}-${python_platform}.whl echo "WHEEL_TO_INSTALL=${WHEEL_TO_INSTALL}" + docker build \ -f Dockerfile \ + --platform=${{ matrix.cpu-arch }} \ --build-arg PYTHON_VERSION=${{ matrix.python-version }} \ --build-arg OS_VARIANT=${{ matrix.os-variant }} \ --build-arg WHEEL_TO_INSTALL=${WHEEL_TO_INSTALL} \ diff --git a/make_wheels.py b/make_wheels.py index c48dec7..a251ca1 100644 --- a/make_wheels.py +++ b/make_wheels.py @@ -1,11 +1,14 @@ import os import hashlib import pathlib +import io +import subprocess import urllib.request import libarchive +import tempfile from email.message import EmailMessage from wheel.wheelfile import WheelFile -from zipfile import ZipInfo, ZIP_DEFLATED +from zipfile import ZipInfo, ZIP_DEFLATED, ZipFile from inspect import cleandoc @@ -46,17 +49,52 @@ 'linux-x64': 'manylinux_2_12_x86_64.manylinux2010_x86_64', 'linux-armv7l': 'manylinux_2_17_armv7l.manylinux2014_armv7l', 'linux-arm64': 'manylinux_2_17_aarch64.manylinux2014_aarch64', - 'linux-x64-musl': 'musllinux_1_1_x86_64' + 'linux-x64-musl': 'musllinux_1_1_x86_64', + 'linux-arm64-musl': 'musllinux_1_1_aarch64' } # https://github.com/nodejs/unofficial-builds/ # Versions added here should match the keys above UNOFFICIAL_NODEJS_BUILDS = {'linux-x64-musl'} +DOCKER_BASED_BUILDS = {"linux-arm64-musl"} -_mismatched_versions = UNOFFICIAL_NODEJS_BUILDS - set(PLATFORMS.keys()) +_mismatched_versions = (UNOFFICIAL_NODEJS_BUILDS|DOCKER_BASED_BUILDS) - set(PLATFORMS.keys()) if _mismatched_versions: raise Exception(f"A version mismatch occurred. Check the usage of {_mismatched_versions}") +def _build_virtual_release_archive(docker_image: str, platform: str) -> bytes: + binaries_to_copy = [x.split("bin/")[1] for x in [*NODE_BINS, *NODE_OTHER_BINS] if x.startswith("bin")] + zip_bytes = io.BytesIO() + with tempfile.TemporaryDirectory() as tmpdirname, ZipFile(zip_bytes, "w") as zip_file: + subprocess.check_call([ + "docker", + "run", + "--rm", + f"--platform={platform}", + f"--volume={tmpdirname}:/external", + "--entrypoint=sh", + docker_image, + "-c", + f""" + for binary in {" ".join(binaries_to_copy)}; do + cp $(which $binary) /external + done + chmod 755 /external/* + """ + ], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + tmpdir_contents = list(pathlib.Path(tmpdirname).glob("*")) + for binary in tmpdir_contents: + with open(binary, "rb") as f: + file_info = ZipInfo( + filename=f"node/bin/{binary.name}", + ) + file_info.external_attr = 0o755 << 16 + zip_file.writestr(file_info, f.read()) + + zip_bytes.seek(0) + return zip_bytes.read() class ReproducibleWheelFile(WheelFile): def writestr(self, zinfo, *args, **kwargs): @@ -186,7 +224,7 @@ def main() -> None: elif entry_name in NODE_OTHER_BINS and NODE_OTHER_BINS[entry_name][1]: other_bin = NODE_OTHER_BINS[entry_name][0] init_imports.append(f'from . import {other_bin} as {other_bin}') - script_name = '/'.join(os.path.normpath(os.path.join(os.path.dirname(entry.name), entry.linkpath)).split('/')[1:]) + script_name = '/'.join(os.path.normpath(os.path.join(os.path.dirname(entry.name), entry.linkpath or other_bin)).split('/')[1:]) contents[f'nodejs/{NODE_OTHER_BINS[entry_name][0]}.py'] = cleandoc(f""" import os, sys from typing import TYPE_CHECKING @@ -312,22 +350,27 @@ def make_nodejs_version(node_version, suffix=''): print('Suffix:', suffix) for node_platform, python_platform in PLATFORMS.items(): - filetype = 'zip' if node_platform.startswith('win-') else 'tar.xz' - if node_platform in UNOFFICIAL_NODEJS_BUILDS: - node_url = f'https://unofficial-builds.nodejs.org/download/release/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' + if node_platform in DOCKER_BASED_BUILDS: + docker_image = f"node:{node_version}-alpine" + print(f'- Making Wheel for {node_platform} from docker image {docker_image}') + node_archive = _build_virtual_release_archive(docker_image=docker_image, platform="linux/arm64") else: - node_url = f'https://nodejs.org/dist/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' - - print(f'- Making Wheel for {node_platform} from {node_url}') - try: - with urllib.request.urlopen(node_url) as request: - node_archive = request.read() - print(f' {node_url}') - print(f' {hashlib.sha256(node_archive).hexdigest()}') - except urllib.error.HTTPError as e: - print(f' {e.code} {e.reason}') - print(f' Skipping {node_platform}') - continue + filetype = 'zip' if node_platform.startswith('win-') else 'tar.xz' + if node_platform in UNOFFICIAL_NODEJS_BUILDS: + node_url = f'https://unofficial-builds.nodejs.org/download/release/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' + else: + node_url = f'https://nodejs.org/dist/v{node_version}/node-v{node_version}-{node_platform}.{filetype}' + + print(f'- Making Wheel for {node_platform} from {node_url}') + try: + with urllib.request.urlopen(node_url) as request: + node_archive: bytes = request.read() + print(f' {node_url}') + print(f' {hashlib.sha256(node_archive).hexdigest()}') + except urllib.error.HTTPError as e: + print(f' {e.code} {e.reason}') + print(f' Skipping {node_platform}') + continue wheel_path = write_nodejs_wheel('dist/', node_version=node_version, From c16cbc1a1e962acdf8d7a222e8e449311221ad9b Mon Sep 17 00:00:00 2001 From: Jacob Roberts Date: Fri, 4 Nov 2022 10:57:53 -0700 Subject: [PATCH 6/6] Switch to using tar, don't copy symlinks for non-node binaries in the bin directory --- .github/workflows/test.yaml | 6 +-- make_wheels.py | 74 ++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b11f10b..fdc970f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -124,12 +124,12 @@ jobs: linux/amd64) python_cpu_arch=x86_64 python_libc_variant=2_12 - manylinx_variant_year=2010 + manylinux_variant_year=2010 ;; linux/arm64) python_cpu_arch=aarch64 python_libc_variant=2_17 - manylinx_variant_year=2014 + manylinux_variant_year=2014 ;; *) echo "Could not parse the CPU architecture" @@ -142,7 +142,7 @@ jobs: python_platform=musllinux_1_1_${python_cpu_arch} ;; slim-buster | slim-bullseye) - python_platform=manylinux_${python_libc_variant}_${python_cpu_arch}.manylinux${manylinx_variant_year}_${python_cpu_arch} + python_platform=manylinux_${python_libc_variant}_${python_cpu_arch}.manylinux${manylinux_variant_year}_${python_cpu_arch} ;; *) echo "Could not parse the OS variant" diff --git a/make_wheels.py b/make_wheels.py index a251ca1..6db33ee 100644 --- a/make_wheels.py +++ b/make_wheels.py @@ -6,9 +6,10 @@ import urllib.request import libarchive import tempfile +import tarfile from email.message import EmailMessage from wheel.wheelfile import WheelFile -from zipfile import ZipInfo, ZIP_DEFLATED, ZipFile +from zipfile import ZipInfo, ZIP_DEFLATED from inspect import cleandoc @@ -63,38 +64,45 @@ raise Exception(f"A version mismatch occurred. Check the usage of {_mismatched_versions}") def _build_virtual_release_archive(docker_image: str, platform: str) -> bytes: - binaries_to_copy = [x.split("bin/")[1] for x in [*NODE_BINS, *NODE_OTHER_BINS] if x.startswith("bin")] - zip_bytes = io.BytesIO() - with tempfile.TemporaryDirectory() as tmpdirname, ZipFile(zip_bytes, "w") as zip_file: - subprocess.check_call([ - "docker", - "run", - "--rm", - f"--platform={platform}", - f"--volume={tmpdirname}:/external", - "--entrypoint=sh", - docker_image, - "-c", - f""" - for binary in {" ".join(binaries_to_copy)}; do - cp $(which $binary) /external - done - chmod 755 /external/* - """ - ], - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - tmpdir_contents = list(pathlib.Path(tmpdirname).glob("*")) + # Since npm etc are symlinks we dont copy them here -- the python files shim + # to the lib/mode_modules directory where the real implementation lives as nodejs + # shebanged executables + raw_binaries_to_copy = [x.split("bin/")[1] for x in NODE_BINS if x.startswith("bin")] + tarfile_bytes = io.BytesIO() + with tempfile.TemporaryDirectory() as tmpdirname, tarfile.open(fileobj=tarfile_bytes, mode="w") as tar: + subprocess.check_call( + [ + "docker", + "run", + "--rm", + f"--platform={platform}", + f"--volume={tmpdirname}:/external", + "--entrypoint=sh", + docker_image, + "-c", + f""" + mkdir /external/bin + mkdir /external/lib + for raw_binary in {" ".join(raw_binaries_to_copy)}; do + cp -P $(which $raw_binary) /external/bin + done + if [ -d /usr/local/lib/node_modules ]; then + cp -R /usr/local/lib/node_modules /external/lib + fi + """ + ], + ) + + tmpdir_contents = list(pathlib.Path(tmpdirname).glob("**/*")) for binary in tmpdir_contents: - with open(binary, "rb") as f: - file_info = ZipInfo( - filename=f"node/bin/{binary.name}", - ) - file_info.external_attr = 0o755 << 16 - zip_file.writestr(file_info, f.read()) - - zip_bytes.seek(0) - return zip_bytes.read() + relative_path = binary.relative_to(tmpdirname) + if binary.is_file(): + tar_info = tar.gettarinfo(name=binary, arcname=str("node" / relative_path)) + with open(binary, "rb") as f: + tar.addfile(tar_info, f) + + tarfile_bytes.seek(0) + return tarfile_bytes.read() class ReproducibleWheelFile(WheelFile): def writestr(self, zinfo, *args, **kwargs): @@ -224,7 +232,7 @@ def main() -> None: elif entry_name in NODE_OTHER_BINS and NODE_OTHER_BINS[entry_name][1]: other_bin = NODE_OTHER_BINS[entry_name][0] init_imports.append(f'from . import {other_bin} as {other_bin}') - script_name = '/'.join(os.path.normpath(os.path.join(os.path.dirname(entry.name), entry.linkpath or other_bin)).split('/')[1:]) + script_name = '/'.join(os.path.normpath(os.path.join(os.path.dirname(entry.name), entry.linkpath)).split('/')[1:]) contents[f'nodejs/{NODE_OTHER_BINS[entry_name][0]}.py'] = cleandoc(f""" import os, sys from typing import TYPE_CHECKING