Skip to content

Commit 68ab338

Browse files
authored
feat: add log_show_mode parameter to control log display (#13)
* feat: add `log_show_mode` parameter to control log display * docs: update README * chore: update ci * chore: update ci * chore: update ci * chore: update ci * chore: update ci * chore: update ci * revert: rollback ci * chore: update ci
1 parent 3c918d3 commit 68ab338

6 files changed

Lines changed: 100 additions & 38 deletions

File tree

.github/workflows/test.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,35 @@ jobs:
3535
sudo apt-get update
3636
sudo apt-get install -y chromium-browser chromium-chromedriver xvfb
3737
38+
- name: Set Chromium binary (Ubuntu)
39+
if: matrix.os == 'ubuntu-latest'
40+
run: |
41+
if [ -x /usr/bin/chromium-browser ]; then
42+
echo "CHROME_BINARY=/usr/bin/chromium-browser" >> $GITHUB_ENV
43+
elif [ -x /usr/bin/chromium ]; then
44+
echo "CHROME_BINARY=/usr/bin/chromium" >> $GITHUB_ENV
45+
fi
46+
3847
- name: Install browser for testing (macOS)
3948
if: matrix.os == 'macos-latest'
4049
run: |
4150
brew install --cask chromium chromedriver
4251
52+
- name: Set Chromium binary (macOS)
53+
if: matrix.os == 'macos-latest'
54+
run: |
55+
echo "CHROME_BINARY=/Applications/Chromium.app/Contents/MacOS/Chromium" >> $GITHUB_ENV
56+
4357
- name: Install browser for testing (Windows)
4458
if: matrix.os == 'windows-latest'
4559
run: |
4660
choco install chromium chromedriver
4761
62+
- name: Set Chromium binary (Windows)
63+
if: matrix.os == 'windows-latest'
64+
run: |
65+
"CHROME_BINARY=C:\Program Files\Chromium\Application\chrome.exe" | Out-File -FilePath $env:GITHUB_ENV -Append
66+
4867
- name: Start virtual display (Ubuntu)
4968
if: matrix.os == 'ubuntu-latest'
5069
run: |
@@ -53,7 +72,7 @@ jobs:
5372
5473
- name: Run tests
5574
run: |
56-
python -m pytest tests/ -v --cov=dash_vite_plugin --cov-report=xml
75+
python -m pytest tests/ -v --headless --cov=dash_vite_plugin --cov-report=xml
5776
env:
5877
DISPLAY: :99
5978

README-zh_CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ VitePlugin 是负责管理 Vite 构建过程的主要插件类。
131131
| download_node | bool | False | 如果未找到是否下载 Node.js |
132132
| node_version | str | '18.17.0' | 要下载的 Node.js 版本 |
133133
| clean_after | bool | False | 构建后是否清理生成的文件 |
134+
| log_show_mode | Literal['all', 'slim', 'hide'] | 'all' | 日志显示模式 ('all' 显示所有日志, 'slim' 显示精简日志, 'hide' 不显示日志) |
134135
| skip_build | bool | False | 是否跳过构建执行 |
135136
| skip_build_if_recent | bool | True | 如果构建文件是最近生成的是否跳过构建 |
136137
| skip_build_time_threshold | int | 5 | 考虑构建文件为最近的时间阈值(秒)|

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ VitePlugin is the main plugin class responsible for managing the Vite build proc
130130
| download_node | bool | False | Whether to download Node.js if not found |
131131
| node_version | str | '18.17.0' | Node.js version to download |
132132
| clean_after | bool | False | Whether to clean up generated files after build |
133+
| log_show_mode | Literal['all', 'slim', 'hide'] | 'all' | Log show mode ('all' for verbose, 'slim' for minimal output, 'hide' for no logs) |
133134
| skip_build | bool | False | Whether to skip build execution |
134135
| skip_build_if_recent | bool | True | Whether to skip build if built file was recently generated |
135136
| skip_build_time_threshold | int | 5 | Time threshold in seconds to consider built file as recent |

dash_vite_plugin/plugin.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dash import Dash, hooks
77
from flask import send_from_directory
88
from py_node_manager import get_logger
9-
from typing import List
9+
from typing import List, Literal
1010
from .utils import NpmPackage, ViteCommand
1111

1212

@@ -29,6 +29,7 @@ def __init__(
2929
download_node: bool = False,
3030
node_version: str = '18.20.8',
3131
clean_after: bool = False,
32+
log_show_mode: Literal['all', 'slim', 'hide'] = 'all',
3233
skip_build: bool = False,
3334
skip_build_if_recent: bool = True,
3435
skip_build_time_threshold: int = 5,
@@ -46,6 +47,7 @@ def __init__(
4647
download_node (bool): Whether to download Node.js if not found
4748
node_version (str): Node.js version to download if download_node is True
4849
clean_after (bool): Whether to clean up generated files after build
50+
log_show_mode (Literal['all', 'slim', 'hide']): Log show mode
4951
skip_build (bool): Whether to skip build execution
5052
skip_build_if_recent (bool): Whether to skip build if built file was recently generated
5153
skip_build_time_threshold (int): Time threshold in seconds to consider built file as recent
@@ -59,6 +61,7 @@ def __init__(
5961
self.download_node = download_node
6062
self.node_version = node_version
6163
self.clean_after = clean_after
64+
self.log_show_mode = log_show_mode
6265
self.skip_build = skip_build
6366
self.skip_build_if_recent = skip_build_if_recent
6467
self.skip_build_time_threshold = skip_build_time_threshold
@@ -71,6 +74,7 @@ def __init__(
7174
download_node=download_node,
7275
node_version=node_version,
7376
is_cli=False,
77+
log_show_mode=log_show_mode,
7478
)
7579
self._clean_files = []
7680
self._clean_dirs = []
@@ -205,10 +209,11 @@ def _should_skip_build(self) -> bool:
205209
file_mod_time = os.path.getmtime(check_index_path)
206210
current_time = time.time()
207211
if current_time - file_mod_time < self.skip_build_time_threshold:
208-
logger.info(
209-
f'⚡ Built assets file was generated recently '
210-
f'({current_time - file_mod_time:.2f}s ago), skipping build...'
211-
)
212+
if self.log_show_mode in ['all', 'slim']:
213+
logger.info(
214+
f'⚡ Built assets file was generated recently '
215+
f'({current_time - file_mod_time:.2f}s ago), skipping build...'
216+
)
212217
return True
213218
return False
214219

dash_vite_plugin/utils.py

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(
3838
download_node: bool,
3939
node_version: str,
4040
is_cli: bool,
41+
log_show_mode: Literal['all', 'slim', 'hide'] = 'all',
4142
):
4243
"""
4344
Initialize the ViteCommand class
@@ -51,8 +52,11 @@ def __init__(
5152
download_node (bool): Whether to download Node.js if not found
5253
node_version (str): Node.js version to download if download_node is True
5354
is_cli (bool): Whether the command is being run from the CLI
55+
log_show_mode (Literal['all', 'slim', 'hide']): Log show mode
5456
"""
55-
node_manager = NodeManager(download_node=download_node, node_version=node_version, is_cli=False)
57+
node_manager = NodeManager(
58+
download_node=download_node, node_version=node_version, is_cli=False, log_show_mode=log_show_mode
59+
)
5660
self.node_path = node_manager.node_path
5761
self.node_env = node_manager.node_env
5862
self.npm_path = node_manager.npm_path
@@ -62,6 +66,7 @@ def __init__(
6266
self.support_less = support_less
6367
self.support_sass = support_sass
6468
self.is_cli = is_cli
69+
self.log_show_mode = log_show_mode
6570
# Ensure the plugin_tmp_dir directory exists
6671
self.plugin_tmp_dir = plugin_tmp_dir
6772
if not os.path.exists(self.plugin_tmp_dir):
@@ -215,7 +220,8 @@ def _install_vite(self) -> None:
215220
Returns:
216221
None
217222
"""
218-
logger.info('📥 Start installing Vite...')
223+
if self.log_show_mode == 'all':
224+
logger.info('📥 Start installing Vite...')
219225
try:
220226
if not self._check_vite():
221227
install_cmd = [
@@ -237,10 +243,12 @@ def _install_vite(self) -> None:
237243
if result.returncode != 0:
238244
raise RuntimeError(result.stderr)
239245

240-
logger.info('✅ Vite installed successfully!')
246+
if self.log_show_mode in ['all', 'slim']:
247+
logger.info('✅ Vite installed successfully!')
241248

242249
except Exception as e:
243-
logger.error(f'❌ Error installing Vite: {e}')
250+
if self.log_show_mode in ['all', 'slim']:
251+
logger.error(f'❌ Error installing Vite: {e}')
244252
raise e
245253

246254
def _install_less(self) -> None:
@@ -250,7 +258,8 @@ def _install_less(self) -> None:
250258
Returns:
251259
None
252260
"""
253-
logger.info('📥 Start installing Less...')
261+
if self.log_show_mode == 'all':
262+
logger.info('📥 Start installing Less...')
254263
try:
255264
if not self._check_less():
256265
install_cmd = [
@@ -270,10 +279,12 @@ def _install_less(self) -> None:
270279
if result.returncode != 0:
271280
raise RuntimeError(result.stderr)
272281

273-
logger.info('✅ Less installed successfully!')
282+
if self.log_show_mode in ['all', 'slim']:
283+
logger.info('✅ Less installed successfully!')
274284

275285
except Exception as e:
276-
logger.error(f'❌ Error installing Less: {e}')
286+
if self.log_show_mode in ['all', 'slim']:
287+
logger.error(f'❌ Error installing Less: {e}')
277288
raise e
278289

279290
def _install_sass(self) -> None:
@@ -283,7 +294,8 @@ def _install_sass(self) -> None:
283294
Returns:
284295
None
285296
"""
286-
logger.info('📥 Start installing Sass...')
297+
if self.log_show_mode == 'all':
298+
logger.info('📥 Start installing Sass...')
287299
try:
288300
if not self._check_sass():
289301
install_cmd = [
@@ -303,10 +315,12 @@ def _install_sass(self) -> None:
303315
if result.returncode != 0:
304316
raise RuntimeError(result.stderr)
305317

306-
logger.info('✅ Sass installed successfully!')
318+
if self.log_show_mode in ['all', 'slim']:
319+
logger.info('✅ Sass installed successfully!')
307320

308321
except Exception as e:
309-
logger.error(f'❌ Error installing Sass: {e}')
322+
if self.log_show_mode in ['all', 'slim']:
323+
logger.error(f'❌ Error installing Sass: {e}')
310324
raise e
311325

312326
def _install_npm_packages(self) -> None:
@@ -316,7 +330,8 @@ def _install_npm_packages(self) -> None:
316330
Returns:
317331
None
318332
"""
319-
logger.info('📥 Start installing npm packages...')
333+
if self.log_show_mode == 'all':
334+
logger.info('📥 Start installing npm packages...')
320335
try:
321336
for package in self.npm_packages:
322337
install_cmd = [
@@ -336,10 +351,12 @@ def _install_npm_packages(self) -> None:
336351
if result.returncode != 0:
337352
raise RuntimeError(result.stderr)
338353

339-
logger.info('✅ npm packages installed successfully!')
354+
if self.log_show_mode in ['all', 'slim']:
355+
logger.info('✅ npm packages installed successfully!')
340356

341357
except Exception as e:
342-
logger.error(f'❌ Error installing npm packages: {e}')
358+
if self.log_show_mode in ['all', 'slim']:
359+
logger.error(f'❌ Error installing npm packages: {e}')
343360
raise e
344361

345362
def init(self) -> Self:
@@ -349,27 +366,28 @@ def init(self) -> Self:
349366
Returns:
350367
Self: The ViteCommand instance
351368
"""
352-
logger.info('🚀 Start initializing Vite...')
369+
if self.log_show_mode == 'all':
370+
logger.info('🚀 Start initializing Vite...')
353371
try:
354372
# Create default config if it doesn't exist
355-
if self.is_cli:
373+
if self.is_cli and self.log_show_mode == 'all':
356374
logger.info('⚙️ Creating Vite config file...')
357375

358376
if not os.path.exists(self.config_js_path):
359-
if self.is_cli:
377+
if self.is_cli and self.log_show_mode == 'all':
360378
logger.info(f'🔍 Config file {self.config_js_path} not found. Creating default config file...')
361379

362380
self.create_default_vite_config()
363381

364-
if self.is_cli:
382+
if self.is_cli and self.log_show_mode == 'all':
365383
logger.info(f'💾 Default config file created at: {self.config_js_path}')
366384

367-
if self.is_cli:
385+
if self.is_cli and self.log_show_mode == 'all':
368386
logger.info('⚙️ Creating index.html file...')
369387

370388
self.create_default_index_html()
371389

372-
if self.is_cli:
390+
if self.is_cli and self.log_show_mode == 'all':
373391
logger.info(f'💾 Default index.html file created at: {self.index_html_path}')
374392

375393
if not self._check_npm_init():
@@ -384,11 +402,12 @@ def init(self) -> Self:
384402
)
385403
if result.returncode != 0:
386404
raise RuntimeError(result.stderr)
387-
388-
logger.info('✅ Vite initialized successfully!')
405+
if self.log_show_mode in ['all', 'slim']:
406+
logger.info('✅ Vite initialized successfully!')
389407

390408
except Exception as e:
391-
logger.error(f'❌ Error initializing Vite: {e}')
409+
if self.log_show_mode in ['all', 'slim']:
410+
logger.error(f'❌ Error initializing Vite: {e}')
392411
raise e
393412

394413
return self
@@ -416,7 +435,8 @@ def build(self) -> Self:
416435
Returns:
417436
Self: The ViteCommand instance
418437
"""
419-
logger.info('🔨 Building assets using Vite...')
438+
if self.log_show_mode == 'all':
439+
logger.info('🔨 Building assets using Vite...')
420440
try:
421441
build_cmd: List[str] = [self.npx_path, 'vite', 'build']
422442

@@ -427,10 +447,12 @@ def build(self) -> Self:
427447
if result.returncode != 0:
428448
raise RuntimeError(result.stderr)
429449

430-
logger.info('✅ Build completed successfully!')
450+
if self.log_show_mode in ['all', 'slim']:
451+
logger.info('✅ Build completed successfully!')
431452

432453
except Exception as e:
433-
logger.error(f'❌ Error building assets using Vite: {e}')
454+
if self.log_show_mode in ['all', 'slim']:
455+
logger.error(f'❌ Error building assets using Vite: {e}')
434456
raise e
435457

436458
return self
@@ -446,7 +468,8 @@ def clean(self, extra_clean_files: List[str], extra_clean_dirs: List[str]) -> Se
446468
Returns:
447469
Self: The ViteCommand instance
448470
"""
449-
logger.info('🧹 Cleaning up generated files...')
471+
if self.log_show_mode == 'all':
472+
logger.info('🧹 Cleaning up generated files...')
450473
try:
451474
files_to_remove = [
452475
self.config_js_path,
@@ -464,25 +487,29 @@ def clean(self, extra_clean_files: List[str], extra_clean_dirs: List[str]) -> Se
464487
if os.path.exists(file_path):
465488
try:
466489
os.remove(file_path)
467-
if self.is_cli:
490+
if self.is_cli and self.log_show_mode == 'all':
468491
logger.info(f'🗑️ Removed {file_path}')
469492
except Exception as e:
470-
logger.warning(f'⚠️ Warning: Could not remove {file_path}: {e}')
493+
if self.log_show_mode in ['all', 'slim']:
494+
logger.warning(f'⚠️ Warning: Could not remove {file_path}: {e}')
471495

472496
# Remove directories
473497
for dir_path in directories_to_remove:
474498
if os.path.exists(dir_path):
475499
try:
476500
shutil.rmtree(dir_path)
477-
if self.is_cli:
501+
if self.is_cli and self.log_show_mode == 'all':
478502
logger.info(f'🗑️ Removed {dir_path}')
479503
except Exception as e:
480-
logger.warning(f'⚠️ Warning: Could not remove {dir_path}: {e}')
504+
if self.log_show_mode in ['all', 'slim']:
505+
logger.warning(f'⚠️ Warning: Could not remove {dir_path}: {e}')
481506

482-
logger.info('✅ Cleanup completed.')
507+
if self.log_show_mode in ['all', 'slim']:
508+
logger.info('✅ Cleanup completed.')
483509

484510
except Exception as e:
485-
logger.error(f'❌ Error cleaning up: {e}')
511+
if self.log_show_mode in ['all', 'slim']:
512+
logger.error(f'❌ Error cleaning up: {e}')
486513
raise e
487514

488515
return self

tests/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
import shutil
55
import tempfile
6+
from selenium.webdriver.chrome.options import Options
67

78

89
# Add the project root to the Python path so we can import the package
@@ -26,3 +27,11 @@ def temp_working_directory():
2627
yield temp_dir
2728
os.chdir(original_cwd)
2829
shutil.rmtree(temp_dir, ignore_errors=True)
30+
31+
32+
def pytest_setup_options():
33+
options = Options()
34+
chrome_binary = os.environ.get('CHROME_BINARY')
35+
if chrome_binary:
36+
options.binary_location = chrome_binary
37+
return options

0 commit comments

Comments
 (0)