From 199ee9d38d6cc2828fd300869dff6d9c18ac069e Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 15:05:17 +0800 Subject: [PATCH 01/10] feat: add `log_show_mode` parameter to control log display --- dash_vite_plugin/plugin.py | 15 ++++--- dash_vite_plugin/utils.py | 91 ++++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/dash_vite_plugin/plugin.py b/dash_vite_plugin/plugin.py index 9d91fea..d9cb64a 100644 --- a/dash_vite_plugin/plugin.py +++ b/dash_vite_plugin/plugin.py @@ -6,7 +6,7 @@ from dash import Dash, hooks from flask import send_from_directory from py_node_manager import get_logger -from typing import List +from typing import List, Literal from .utils import NpmPackage, ViteCommand @@ -29,6 +29,7 @@ def __init__( download_node: bool = False, node_version: str = '18.20.8', clean_after: bool = False, + log_show_mode: Literal['all', 'slim', 'hide'] = 'all', skip_build: bool = False, skip_build_if_recent: bool = True, skip_build_time_threshold: int = 5, @@ -46,6 +47,7 @@ def __init__( download_node (bool): Whether to download Node.js if not found node_version (str): Node.js version to download if download_node is True clean_after (bool): Whether to clean up generated files after build + log_show_mode (Literal['all', 'slim', 'hide']): Log show mode skip_build (bool): Whether to skip build execution skip_build_if_recent (bool): Whether to skip build if built file was recently generated skip_build_time_threshold (int): Time threshold in seconds to consider built file as recent @@ -59,6 +61,7 @@ def __init__( self.download_node = download_node self.node_version = node_version self.clean_after = clean_after + self.log_show_mode = log_show_mode self.skip_build = skip_build self.skip_build_if_recent = skip_build_if_recent self.skip_build_time_threshold = skip_build_time_threshold @@ -71,6 +74,7 @@ def __init__( download_node=download_node, node_version=node_version, is_cli=False, + log_show_mode=log_show_mode, ) self._clean_files = [] self._clean_dirs = [] @@ -205,10 +209,11 @@ def _should_skip_build(self) -> bool: file_mod_time = os.path.getmtime(check_index_path) current_time = time.time() if current_time - file_mod_time < self.skip_build_time_threshold: - logger.info( - f'⚡ Built assets file was generated recently ' - f'({current_time - file_mod_time:.2f}s ago), skipping build...' - ) + if self.log_show_mode in ['all', 'slim']: + logger.info( + f'⚡ Built assets file was generated recently ' + f'({current_time - file_mod_time:.2f}s ago), skipping build...' + ) return True return False diff --git a/dash_vite_plugin/utils.py b/dash_vite_plugin/utils.py index 5700436..5dffe1a 100644 --- a/dash_vite_plugin/utils.py +++ b/dash_vite_plugin/utils.py @@ -38,6 +38,7 @@ def __init__( download_node: bool, node_version: str, is_cli: bool, + log_show_mode: Literal['all', 'slim', 'hide'] = 'all', ): """ Initialize the ViteCommand class @@ -51,8 +52,11 @@ def __init__( download_node (bool): Whether to download Node.js if not found node_version (str): Node.js version to download if download_node is True is_cli (bool): Whether the command is being run from the CLI + log_show_mode (Literal['all', 'slim', 'hide']): Log show mode """ - node_manager = NodeManager(download_node=download_node, node_version=node_version, is_cli=False) + node_manager = NodeManager( + download_node=download_node, node_version=node_version, is_cli=False, log_show_mode=log_show_mode + ) self.node_path = node_manager.node_path self.node_env = node_manager.node_env self.npm_path = node_manager.npm_path @@ -62,6 +66,7 @@ def __init__( self.support_less = support_less self.support_sass = support_sass self.is_cli = is_cli + self.log_show_mode = log_show_mode # Ensure the plugin_tmp_dir directory exists self.plugin_tmp_dir = plugin_tmp_dir if not os.path.exists(self.plugin_tmp_dir): @@ -215,7 +220,8 @@ def _install_vite(self) -> None: Returns: None """ - logger.info('📥 Start installing Vite...') + if self.log_show_mode == 'all': + logger.info('📥 Start installing Vite...') try: if not self._check_vite(): install_cmd = [ @@ -237,10 +243,12 @@ def _install_vite(self) -> None: if result.returncode != 0: raise RuntimeError(result.stderr) - logger.info('✅ Vite installed successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Vite installed successfully!') except Exception as e: - logger.error(f'❌ Error installing Vite: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error installing Vite: {e}') raise e def _install_less(self) -> None: @@ -250,7 +258,8 @@ def _install_less(self) -> None: Returns: None """ - logger.info('📥 Start installing Less...') + if self.log_show_mode == 'all': + logger.info('📥 Start installing Less...') try: if not self._check_less(): install_cmd = [ @@ -270,10 +279,12 @@ def _install_less(self) -> None: if result.returncode != 0: raise RuntimeError(result.stderr) - logger.info('✅ Less installed successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Less installed successfully!') except Exception as e: - logger.error(f'❌ Error installing Less: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error installing Less: {e}') raise e def _install_sass(self) -> None: @@ -283,7 +294,8 @@ def _install_sass(self) -> None: Returns: None """ - logger.info('📥 Start installing Sass...') + if self.log_show_mode == 'all': + logger.info('📥 Start installing Sass...') try: if not self._check_sass(): install_cmd = [ @@ -303,10 +315,12 @@ def _install_sass(self) -> None: if result.returncode != 0: raise RuntimeError(result.stderr) - logger.info('✅ Sass installed successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Sass installed successfully!') except Exception as e: - logger.error(f'❌ Error installing Sass: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error installing Sass: {e}') raise e def _install_npm_packages(self) -> None: @@ -316,7 +330,8 @@ def _install_npm_packages(self) -> None: Returns: None """ - logger.info('📥 Start installing npm packages...') + if self.log_show_mode == 'all': + logger.info('📥 Start installing npm packages...') try: for package in self.npm_packages: install_cmd = [ @@ -336,10 +351,12 @@ def _install_npm_packages(self) -> None: if result.returncode != 0: raise RuntimeError(result.stderr) - logger.info('✅ npm packages installed successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ npm packages installed successfully!') except Exception as e: - logger.error(f'❌ Error installing npm packages: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error installing npm packages: {e}') raise e def init(self) -> Self: @@ -349,27 +366,28 @@ def init(self) -> Self: Returns: Self: The ViteCommand instance """ - logger.info('🚀 Start initializing Vite...') + if self.log_show_mode == 'all': + logger.info('🚀 Start initializing Vite...') try: # Create default config if it doesn't exist - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info('⚙️ Creating Vite config file...') if not os.path.exists(self.config_js_path): - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info(f'🔍 Config file {self.config_js_path} not found. Creating default config file...') self.create_default_vite_config() - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info(f'💾 Default config file created at: {self.config_js_path}') - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info('⚙️ Creating index.html file...') self.create_default_index_html() - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info(f'💾 Default index.html file created at: {self.index_html_path}') if not self._check_npm_init(): @@ -384,11 +402,12 @@ def init(self) -> Self: ) if result.returncode != 0: raise RuntimeError(result.stderr) - - logger.info('✅ Vite initialized successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Vite initialized successfully!') except Exception as e: - logger.error(f'❌ Error initializing Vite: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error initializing Vite: {e}') raise e return self @@ -416,7 +435,8 @@ def build(self) -> Self: Returns: Self: The ViteCommand instance """ - logger.info('🔨 Building assets using Vite...') + if self.log_show_mode == 'all': + logger.info('🔨 Building assets using Vite...') try: build_cmd: List[str] = [self.npx_path, 'vite', 'build'] @@ -427,10 +447,12 @@ def build(self) -> Self: if result.returncode != 0: raise RuntimeError(result.stderr) - logger.info('✅ Build completed successfully!') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Build completed successfully!') except Exception as e: - logger.error(f'❌ Error building assets using Vite: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error building assets using Vite: {e}') raise e return self @@ -446,7 +468,8 @@ def clean(self, extra_clean_files: List[str], extra_clean_dirs: List[str]) -> Se Returns: Self: The ViteCommand instance """ - logger.info('🧹 Cleaning up generated files...') + if self.log_show_mode == 'all': + logger.info('🧹 Cleaning up generated files...') try: files_to_remove = [ self.config_js_path, @@ -464,25 +487,29 @@ def clean(self, extra_clean_files: List[str], extra_clean_dirs: List[str]) -> Se if os.path.exists(file_path): try: os.remove(file_path) - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info(f'🗑️ Removed {file_path}') except Exception as e: - logger.warning(f'⚠️ Warning: Could not remove {file_path}: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.warning(f'⚠️ Warning: Could not remove {file_path}: {e}') # Remove directories for dir_path in directories_to_remove: if os.path.exists(dir_path): try: shutil.rmtree(dir_path) - if self.is_cli: + if self.is_cli and self.log_show_mode == 'all': logger.info(f'🗑️ Removed {dir_path}') except Exception as e: - logger.warning(f'⚠️ Warning: Could not remove {dir_path}: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.warning(f'⚠️ Warning: Could not remove {dir_path}: {e}') - logger.info('✅ Cleanup completed.') + if self.log_show_mode in ['all', 'slim']: + logger.info('✅ Cleanup completed.') except Exception as e: - logger.error(f'❌ Error cleaning up: {e}') + if self.log_show_mode in ['all', 'slim']: + logger.error(f'❌ Error cleaning up: {e}') raise e return self From 9836b4f129af6e0f1edbe7487fcd0f3f0c190bf8 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 15:05:47 +0800 Subject: [PATCH 02/10] docs: update README --- README-zh_CN.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README-zh_CN.md b/README-zh_CN.md index 8a46f10..27edf1e 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -131,6 +131,7 @@ VitePlugin 是负责管理 Vite 构建过程的主要插件类。 | download_node | bool | False | 如果未找到是否下载 Node.js | | node_version | str | '18.17.0' | 要下载的 Node.js 版本 | | clean_after | bool | False | 构建后是否清理生成的文件 | +| log_show_mode | Literal['all', 'slim', 'hide'] | 'all' | 日志显示模式 ('all' 显示所有日志, 'slim' 显示精简日志, 'hide' 不显示日志) | | skip_build | bool | False | 是否跳过构建执行 | | skip_build_if_recent | bool | True | 如果构建文件是最近生成的是否跳过构建 | | skip_build_time_threshold | int | 5 | 考虑构建文件为最近的时间阈值(秒)| diff --git a/README.md b/README.md index 97cca68..a111731 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ VitePlugin is the main plugin class responsible for managing the Vite build proc | download_node | bool | False | Whether to download Node.js if not found | | node_version | str | '18.17.0' | Node.js version to download | | clean_after | bool | False | Whether to clean up generated files after build | +| log_show_mode | Literal['all', 'slim', 'hide'] | 'all' | Log show mode ('all' for verbose, 'slim' for minimal output, 'hide' for no logs) | | skip_build | bool | False | Whether to skip build execution | | skip_build_if_recent | bool | True | Whether to skip build if built file was recently generated | | skip_build_time_threshold | int | 5 | Time threshold in seconds to consider built file as recent | From 6bff8cfcdf2c0daa7d9b551e05b6600925b457bc Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 15:51:36 +0800 Subject: [PATCH 03/10] chore: update ci --- .github/workflows/test.yml | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7d040e9..a1f45d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,21 +29,11 @@ jobs: pip install -e . pip install -r requirements-dev.txt - - name: Install browser for testing (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y chromium-browser chromium-chromedriver xvfb - - - name: Install browser for testing (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install --cask chromium chromedriver - - - name: Install browser for testing (Windows) - if: matrix.os == 'windows-latest' - run: | - choco install chromium chromedriver + - name: Install browser for testing + uses: browser-actions/setup-chrome@latest + with: + chrome-version: 'latest' + install-chromedriver: true - name: Start virtual display (Ubuntu) if: matrix.os == 'ubuntu-latest' From 5bfc8c627b7e64a88e94055a4bdf3cb60f7d22a1 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 15:56:26 +0800 Subject: [PATCH 04/10] chore: update ci --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a1f45d3..3466830 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,7 @@ jobs: uses: browser-actions/setup-chrome@latest with: chrome-version: 'latest' + install-dependencies: true install-chromedriver: true - name: Start virtual display (Ubuntu) From 053637ccf3cf2a13b5d92ed650c2b8c87006134a Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 16:03:07 +0800 Subject: [PATCH 05/10] chore: update ci --- .github/workflows/test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3466830..29fcd70 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,8 +32,6 @@ jobs: - name: Install browser for testing uses: browser-actions/setup-chrome@latest with: - chrome-version: 'latest' - install-dependencies: true install-chromedriver: true - name: Start virtual display (Ubuntu) From 59f2670466b3175ca5e8c903ab31145a369c8a52 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 16:06:48 +0800 Subject: [PATCH 06/10] chore: update ci --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29fcd70..3e210a8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: pip install -r requirements-dev.txt - name: Install browser for testing - uses: browser-actions/setup-chrome@latest + uses: browser-actions/setup-chrome@v2 with: install-chromedriver: true From c9255d117f222a2ba765d8239ed7d1958cec6fc2 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 16:19:54 +0800 Subject: [PATCH 07/10] chore: update ci --- .github/workflows/test.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e210a8..f0a3aaa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,10 +30,17 @@ jobs: pip install -r requirements-dev.txt - name: Install browser for testing + id: setup-chrome uses: browser-actions/setup-chrome@v2 with: install-chromedriver: true + - name: Configure Chrome for Dash testing + shell: bash + run: | + echo "DASH_TEST_CHROMEPATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" + echo "$(dirname '${{ steps.setup-chrome.outputs.chromedriver-path }}')" >> "$GITHUB_PATH" + - name: Start virtual display (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | From 55b26a69bb2972de4e8fe187899e34a89b68625a Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 16:39:27 +0800 Subject: [PATCH 08/10] chore: update ci --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f0a3aaa..7b8957a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: - name: Run tests run: | - python -m pytest tests/ -v --cov=dash_vite_plugin --cov-report=xml + python -m pytest tests/ -v --headless --cov=dash_vite_plugin --cov-report=xml env: DISPLAY: :99 From 481c57c6c4ff0a7e7ad1c64684fdc5579517f5eb Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 5 Mar 2026 16:48:34 +0800 Subject: [PATCH 09/10] revert: rollback ci --- .github/workflows/test.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7b8957a..5b5c9d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,17 +29,21 @@ jobs: pip install -e . pip install -r requirements-dev.txt - - name: Install browser for testing - id: setup-chrome - uses: browser-actions/setup-chrome@v2 - with: - install-chromedriver: true + - name: Install browser for testing (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y chromium-browser chromium-chromedriver xvfb + + - name: Install browser for testing (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install --cask chromium chromedriver - - name: Configure Chrome for Dash testing - shell: bash + - name: Install browser for testing (Windows) + if: matrix.os == 'windows-latest' run: | - echo "DASH_TEST_CHROMEPATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" - echo "$(dirname '${{ steps.setup-chrome.outputs.chromedriver-path }}')" >> "$GITHUB_PATH" + choco install chromium chromedriver - name: Start virtual display (Ubuntu) if: matrix.os == 'ubuntu-latest' From c62b77d23353f0556d64ab7e84353043ffc3d471 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 6 Mar 2026 08:51:08 +0800 Subject: [PATCH 10/10] chore: update ci --- .github/workflows/test.yml | 19 +++++++++++++++++++ tests/conftest.py | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b5c9d1..4ac2db8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,16 +35,35 @@ jobs: sudo apt-get update sudo apt-get install -y chromium-browser chromium-chromedriver xvfb + - name: Set Chromium binary (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + if [ -x /usr/bin/chromium-browser ]; then + echo "CHROME_BINARY=/usr/bin/chromium-browser" >> $GITHUB_ENV + elif [ -x /usr/bin/chromium ]; then + echo "CHROME_BINARY=/usr/bin/chromium" >> $GITHUB_ENV + fi + - name: Install browser for testing (macOS) if: matrix.os == 'macos-latest' run: | brew install --cask chromium chromedriver + - name: Set Chromium binary (macOS) + if: matrix.os == 'macos-latest' + run: | + echo "CHROME_BINARY=/Applications/Chromium.app/Contents/MacOS/Chromium" >> $GITHUB_ENV + - name: Install browser for testing (Windows) if: matrix.os == 'windows-latest' run: | choco install chromium chromedriver + - name: Set Chromium binary (Windows) + if: matrix.os == 'windows-latest' + run: | + "CHROME_BINARY=C:\Program Files\Chromium\Application\chrome.exe" | Out-File -FilePath $env:GITHUB_ENV -Append + - name: Start virtual display (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | diff --git a/tests/conftest.py b/tests/conftest.py index 35bc382..46ba578 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import sys import shutil import tempfile +from selenium.webdriver.chrome.options import Options # Add the project root to the Python path so we can import the package @@ -26,3 +27,11 @@ def temp_working_directory(): yield temp_dir os.chdir(original_cwd) shutil.rmtree(temp_dir, ignore_errors=True) + + +def pytest_setup_options(): + options = Options() + chrome_binary = os.environ.get('CHROME_BINARY') + if chrome_binary: + options.binary_location = chrome_binary + return options