ensure-node 0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ensure_node-0.0.0/PKG-INFO +31 -0
- ensure_node-0.0.0/README.md +20 -0
- ensure_node-0.0.0/pyproject.toml +23 -0
- ensure_node-0.0.0/src/ensure_node/__init__.py +3 -0
- ensure_node-0.0.0/src/ensure_node/downloader.py +32 -0
- ensure_node-0.0.0/src/ensure_node/ensure_node.py +42 -0
- ensure_node-0.0.0/src/ensure_node/py.typed +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ensure-node
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Ensure Node.js to be installed.
|
|
5
|
+
Author: Kl1nge5
|
|
6
|
+
Author-email: Kl1nge5 <ninthseason@qq.com>
|
|
7
|
+
Requires-Dist: httpx>=0.28.1
|
|
8
|
+
Requires-Dist: tqdm>=4.67.3
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# ensure-node
|
|
13
|
+
|
|
14
|
+
`ensure-node` 是一个轻量 Python 工具库,用来确保指定版本的 Node.js 发行包就绪。
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from ensure_node import ensure_node
|
|
18
|
+
import subprocess
|
|
19
|
+
# 安装指定版本的 Node.js
|
|
20
|
+
npx, node, npm = ensure_node("https://nodejs.org/dist/latest/node-v25.8.2-win-x64.zip")
|
|
21
|
+
# 使用相关工具
|
|
22
|
+
completed_process = subprocess.run([
|
|
23
|
+
str(npx),
|
|
24
|
+
"--version"
|
|
25
|
+
], capture_output=True)
|
|
26
|
+
print(completed_process.stdout.decode())
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
目前仅在 Windows 平台上测试过,可能支持 Linux 平台,不支持 MacOS 平台。
|
|
30
|
+
|
|
31
|
+
只支持 .zip / .tar.gz / .tar.xz 格式的文件。
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ensure-node
|
|
2
|
+
|
|
3
|
+
`ensure-node` 是一个轻量 Python 工具库,用来确保指定版本的 Node.js 发行包就绪。
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from ensure_node import ensure_node
|
|
7
|
+
import subprocess
|
|
8
|
+
# 安装指定版本的 Node.js
|
|
9
|
+
npx, node, npm = ensure_node("https://nodejs.org/dist/latest/node-v25.8.2-win-x64.zip")
|
|
10
|
+
# 使用相关工具
|
|
11
|
+
completed_process = subprocess.run([
|
|
12
|
+
str(npx),
|
|
13
|
+
"--version"
|
|
14
|
+
], capture_output=True)
|
|
15
|
+
print(completed_process.stdout.decode())
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
目前仅在 Windows 平台上测试过,可能支持 Linux 平台,不支持 MacOS 平台。
|
|
19
|
+
|
|
20
|
+
只支持 .zip / .tar.gz / .tar.xz 格式的文件。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ensure-node"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
description = "Ensure Node.js to be installed."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Kl1nge5", email = "ninthseason@qq.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"httpx>=0.28.1",
|
|
12
|
+
"tqdm>=4.67.3",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["uv_build>=0.9.18,<0.10.0"]
|
|
17
|
+
build-backend = "uv_build"
|
|
18
|
+
|
|
19
|
+
[dependency-groups]
|
|
20
|
+
dev = [
|
|
21
|
+
"pytest>=9.0.2",
|
|
22
|
+
"ruff>=0.15.8",
|
|
23
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import URL
|
|
3
|
+
from tqdm import tqdm
|
|
4
|
+
import pathlib
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
KB = 1024
|
|
8
|
+
MB = 1024 * 1024
|
|
9
|
+
|
|
10
|
+
def stream_downlaod(url: URL | str, save_path: pathlib.Path, chunk_size: int = 1 * MB, delay_every_chunk: float = 0) -> None:
|
|
11
|
+
with httpx.stream("GET", url) as r:
|
|
12
|
+
content_length = int(r.headers.get("Content-Length", 0))
|
|
13
|
+
save_path.parent.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
file_desc = save_path.open("wb")
|
|
15
|
+
|
|
16
|
+
progress_bar = tqdm(total=content_length, unit="bytes", leave=False)
|
|
17
|
+
if delay_every_chunk > 0:
|
|
18
|
+
for chunk in r.iter_bytes(chunk_size):
|
|
19
|
+
file_desc.write(chunk)
|
|
20
|
+
progress_bar.update(chunk_size)
|
|
21
|
+
time.sleep(delay_every_chunk)
|
|
22
|
+
else:
|
|
23
|
+
for chunk in r.iter_bytes(chunk_size):
|
|
24
|
+
file_desc.write(chunk)
|
|
25
|
+
progress_bar.update(chunk_size)
|
|
26
|
+
|
|
27
|
+
file_desc.close()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def fetch_file_metadata(url: URL | str):
|
|
31
|
+
resp = httpx.head(url)
|
|
32
|
+
print(resp.headers)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from .downloader import stream_downlaod
|
|
3
|
+
import shutil
|
|
4
|
+
|
|
5
|
+
class NodeTriple:
|
|
6
|
+
def __init__(self, npx: Path, node: Path, npm: Path) -> None:
|
|
7
|
+
self.npx = npx
|
|
8
|
+
self.node = node
|
|
9
|
+
self.npm = npm
|
|
10
|
+
|
|
11
|
+
def __repr__(self) -> str:
|
|
12
|
+
return f"{{\n\tnpx: {self.npx}\n\tnode: {self.node}\n\tnpm: {self.npm}\n}}"
|
|
13
|
+
|
|
14
|
+
def __iter__(self):
|
|
15
|
+
yield self.npx
|
|
16
|
+
yield self.node
|
|
17
|
+
yield self.npm
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def ensure_node(node_url: str,
|
|
21
|
+
save_dir: Path = Path.home() / ".ensure_node") -> NodeTriple:
|
|
22
|
+
cache_dir = save_dir / "cache"
|
|
23
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
24
|
+
filename = node_url.split("/")[-1]
|
|
25
|
+
file_identity = filename.strip(".zip").strip(".tar.gz").strip(".tar.xz")
|
|
26
|
+
file_identity_path = save_dir / file_identity
|
|
27
|
+
file_save_path = cache_dir / filename
|
|
28
|
+
if file_identity_path.exists():
|
|
29
|
+
return _return_triple(file_identity, file_identity_path)
|
|
30
|
+
stream_downlaod(node_url, file_save_path)
|
|
31
|
+
shutil.unpack_archive(file_save_path, save_dir)
|
|
32
|
+
return _return_triple(file_identity, file_identity_path)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _return_triple(file_identity, file_identity_path) -> NodeTriple:
|
|
36
|
+
if "win" in file_identity:
|
|
37
|
+
return NodeTriple(file_identity_path / "npx.cmd", file_identity_path / "node.exe", file_identity_path / "npm.cmd")
|
|
38
|
+
if "linux" in file_identity:
|
|
39
|
+
return NodeTriple(file_identity_path / "bin" / "npx", \
|
|
40
|
+
file_identity_path / "bin" / "node", \
|
|
41
|
+
file_identity_path / "bin" / "npm")
|
|
42
|
+
raise RuntimeError
|
|
File without changes
|