Skip to content

Commit 860e601

Browse files
NewFutureCopilot
andauthored
fix(pypi): patch.py version (NewFuture#482)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent f84f56c commit 860e601

4 files changed

Lines changed: 83 additions & 44 deletions

File tree

.github/patch.py

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
#!/usr/bin/env python3
22

3+
import sys
34
import os
45
import re
6+
import urllib.request
57
import time
8+
import json
9+
from datetime import datetime, timezone
610

711
ROOT = "."
812
init_py_path = os.path.join(ROOT, "ddns", "__init__.py")
@@ -153,32 +157,83 @@ def remove_python2_compatibility(pyfile):
153157
print(f"Removed python2 compatibility from {pyfile}")
154158

155159

156-
def extract_version_from_env():
157-
"""
158-
从环境变量中提取版本号
159-
"""
160-
ref = os.environ.get("GITHUB_REF_NAME")
161-
if not ref:
162-
return time.strftime("0.0.%m%d.%H%M") # 默认版本号
163-
if ref and ref.startswith("v"):
164-
return ref[1:] # 去掉前缀 'v'
165-
return ref # 返回原始版本号
160+
def get_latest_tag():
161+
url = "https://api.github.com/repos/NewFuture/DDNS/tags?per_page=1"
162+
try:
163+
with urllib.request.urlopen(url) as response:
164+
data = json.load(response)
165+
if data and isinstance(data, list):
166+
return data[0]['name'] # 获取第一个 tag 的 name
167+
except Exception as e:
168+
print("Error fetching tag:", e)
169+
return None
170+
171+
172+
def normalize_tag(tag: str) -> str:
173+
v = tag.lower().lstrip("v")
174+
v = re.sub(r"-beta(\d*)", r"b\1", v)
175+
v = re.sub(r"-alpha(\d*)", r"a\1", v)
176+
v = re.sub(r"-rc(\d*)", r"rc\1", v)
177+
return v
178+
179+
180+
def ten_minute_bucket_id():
181+
epoch_minutes = int(time.time() // 60) # 当前时间(分钟级)
182+
bucket = epoch_minutes // 10 # 每10分钟为一个 bucket
183+
return bucket % 65536 # 限制在 0~65535 (2**16)
184+
185+
186+
def generate_version():
187+
ref = os.environ.get('GITHUB_REF_NAME', '')
188+
if re.match(r"^v\d+\.\d+", ref):
189+
return normalize_tag(ref)
190+
191+
base = "4.0.0"
192+
suffix = ten_minute_bucket_id()
193+
if ref == "master" or ref == "main":
194+
tag = get_latest_tag()
195+
if tag:
196+
base = normalize_tag(tag)
197+
198+
return f"{base}.dev{suffix}"
199+
200+
201+
def replace_version_and_date(pyfile: str, version: str, date_str: str):
202+
with open(pyfile, 'r', encoding="utf-8") as f:
203+
text = f.read()
204+
text = text.replace("${BUILD_VERSION}", version)
205+
text = text.replace("${BUILD_DATE}", date_str)
206+
if text is not None:
207+
with open(pyfile, 'w', encoding="utf-8") as f:
208+
f.write(text)
209+
print(f"Updated {pyfile}: version={version}, date={date_str}")
210+
else:
211+
exit(1)
166212

167213

168214
def main():
169215
"""
170216
遍历所有py文件并替换兼容导入,同时更新nuitka版本号
171217
"""
218+
if len(sys.argv) > 1 and sys.argv[1].lower() != 'version':
219+
print(f'unknown arguments: {sys.argv}')
220+
exit(1)
221+
version = generate_version()
222+
date_str = datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
223+
print(f"Version: {version}")
224+
print(f"Date: {date_str}")
225+
226+
# 修改__init__.py 中的 __version__
227+
replace_version_and_date(init_py_path, version, date_str)
228+
if len(sys.argv) > 1 and sys.argv[1].lower() == 'version':
229+
# python version only
230+
exit(0)
231+
172232
run_py_path = os.path.join(ROOT, "run.py")
173-
version = extract_version_from_env()
174233
update_nuitka_version(run_py_path, version)
175234
add_nuitka_file_description(run_py_path)
176235
add_nuitka_include_modules(run_py_path)
177236

178-
# 修改__init__.py 中的 __version__
179-
180-
replace_version_in_init(version, init_py_path)
181-
182237
changed_files = 0
183238
for dirpath, _, filenames in os.walk(ROOT):
184239
for fname in filenames:
@@ -190,21 +245,5 @@ def main():
190245
print(f"Total processed files: {changed_files}")
191246

192247

193-
def replace_version_in_init(version, init_py_path):
194-
"""
195-
替换 ddns/__init__.py 中的 __version__ 变量
196-
"""
197-
version_str = f'v{version}@{time.strftime("%Y-%m-%dT%H:%M:%S")}'
198-
with open(init_py_path, "r", encoding="utf-8") as f:
199-
content = f.read()
200-
new_content = re.sub(
201-
r'__version__\s*=\s*[\'"]([^\'"]+)[\'"]', f'__version__ = "{version_str}"', content
202-
)
203-
if new_content != content:
204-
with open(init_py_path, "w", encoding="utf-8") as f:
205-
f.write(new_content)
206-
print(f"Updated __version__ in {init_py_path} to {version_str}")
207-
208-
209248
if __name__ == "__main__":
210249
main()

.github/workflows/build.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,8 @@ jobs:
8888
with:
8989
python-version: "3.x"
9090
- name: Install dependencies
91-
run: |
92-
python -m pip install --upgrade pip
93-
pip install build setuptools-scm
91+
run: pip install build
92+
- run: python3 .github/patch.py version
9493
- run: sed -i -E 's#([("])/doc/#\1https://ddns.newfuture.cc/doc/#g' README.md
9594
- name: Build package
9695
run: python -m build --sdist --wheel --outdir dist/

ddns/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55

66
__description__ = "automatically update DNS records to my IP [域名自动指向本机IP]"
77

8-
# 二进制 编译时,版本会被替换
9-
__version__ = "4.0.0"
8+
# 编译时,版本会被替换
9+
__version__ = "${BUILD_VERSION}"
10+
11+
# 时间也会被替换掉
12+
build_date = "${BUILD_DATE}"
1013

1114
__doc__ = """
1215
ddns[%s]

pyproject.toml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11

2-
[build-system] #remove for python2
2+
#[build-system] #remove for python2
33
#requires = ["setuptools>=64.0", "wheel", "setuptools_scm"]
4-
requires=[]
5-
build-backend = "setuptools.build_meta"
6-
7-
[tool.setuptools_scm]
8-
local_scheme = "no-local-version"
4+
#build-backend = "setuptools.build_meta"
5+
#[tool.setuptools_scm]
6+
#local_scheme = "no-local-version"
97

108
[project]
119
name = "ddns"
@@ -71,8 +69,8 @@ py-modules = ["ddns","ddns.provider", "ddns.util"]
7169

7270

7371

74-
# [tool.setuptools.dynamic]
75-
# version = { attr = "ddns.__version__" }
72+
[tool.setuptools.dynamic]
73+
version = { attr = "ddns.__version__" }
7674
# description = { attr = "ddns.__description__" }
7775

7876

0 commit comments

Comments
 (0)