fix: prevent mimetypes hang on Windows by skipping registry init (#2059)

Co-authored-by: E <e@local.com>
Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
This commit is contained in:
yejmin
2026-07-22 23:36:06 +08:00
committed by GitHub
parent a54f46e1ec
commit b275b4ebea
3 changed files with 101 additions and 0 deletions

View File

@@ -19,6 +19,17 @@ import asyncio
import json
import logging
import mimetypes
import sys
if sys.platform == "win32" and not mimetypes.inited:
_orig_read_windows_registry = getattr(mimetypes.MimeTypes, 'read_windows_registry', None)
if _orig_read_windows_registry is not None:
mimetypes.MimeTypes.read_windows_registry = lambda self, strict=True: None
try: mimetypes.init()
finally: mimetypes.MimeTypes.read_windows_registry = _orig_read_windows_registry
else:
mimetypes.init()
import os
import re
from contextlib import asynccontextmanager, suppress

View File

@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- [新功能] Tushare 数据源支持通过 `TUSHARE_HTTP_URL` 环境变量自定义接入地址,便于网络无法直达 `api.tushare.pro` 时切换自建网关或第三方兼容镜像留空保持官方默认地址不变fixes #1985
- [文档] `.env.example``.github/workflows/00-daily-analysis.yml` 同步映射 `TUSHARE_HTTP_URL`,避免出现"配置项有但 workflow 漏映射"的半修状态
- [修复] #2051 PR Review 的特权 `pull_request_target` 流程不再检出 fork PR head敏感文件、标签、报告与 AI 审查统一通过 GitHub API 将 PR 元数据和 diff 作为数据读取只执行主分支可信脚本Python 语法、Flake8、确定性检查和离线测试继续由无 secrets 的 `pull_request` CI / `backend-gate` 执行,兼容 `actions/checkout` 新增的 fork checkout 安全保护。
- [修复] 修复 Windows 上 mimetypes 冷启动时读取注册表导致的进程卡死
## [3.27.0] - 2026-07-19

View File

@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
"""Tests for mimetypes cold-start behaviour on Windows."""
import importlib
import mimetypes
import sys
import unittest
from unittest.mock import patch
class MimetypesWindowsInitTestCase(unittest.TestCase):
"""Cold-start: Windows skips registry; non-Windows keeps full MIME db."""
def setUp(self):
self._types_map_backup = dict(mimetypes.types_map)
def tearDown(self):
mimetypes.types_map.clear()
mimetypes.types_map.update(self._types_map_backup)
@staticmethod
def _simulate_cold_start():
mimetypes.inited = False
mimetypes._db = None
def test_windows_cold_import_skips_registry(self):
"""Windows cold-start must not call read_windows_registry."""
import api.app
self._simulate_cold_start()
with patch("sys.platform", "win32"), \
patch.object(mimetypes.MimeTypes, "read_windows_registry") as mock_registry:
importlib.reload(api.app)
mock_registry.assert_not_called()
def test_non_windows_retains_full_mime_guessing(self):
"""Non-Windows must NOT replace the system MIME database."""
import api.app
self._simulate_cold_start()
with patch("sys.platform", "linux"):
importlib.reload(api.app)
self.assertEqual(
mimetypes.guess_type("index.html")[0],
"text/html",
"HTML must still be detected on non-Windows",
)
self.assertEqual(
mimetypes.guess_type("test.pdf")[0],
"application/pdf",
"PDF must still be detected on non-Windows",
)
def test_types_map_consistent_with_db(self):
"""types_map and _db.types_map[True] must be the same object."""
import api.app
self._simulate_cold_start()
with patch("sys.platform", "win32"):
importlib.reload(api.app)
self.assertIs(
mimetypes.types_map,
mimetypes._db.types_map[True],
"types_map must reference _db internals (no split-brain)",
)
def test_frontend_mime_types_registered_after_init(self):
"""_register_frontend_asset_mime_types must work after cold-start init."""
import api.app
self._simulate_cold_start()
with patch("sys.platform", "win32"):
importlib.reload(api.app)
api.app._register_frontend_asset_mime_types()
self.assertEqual(
mimetypes.guess_type("app.js")[0], "text/javascript"
)
self.assertEqual(
mimetypes.guess_type("style.css")[0], "text/css"
)
if __name__ == "__main__":
unittest.main()