Feature/delta team/epic r04 #7
@@ -34,10 +34,14 @@ jobs:
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: pip
|
||||
cache-dependency-path: cowork_local/requirements-test.txt
|
||||
cache-dependency-path: cowork_local/requirements.txt
|
||||
|
||||
- name: Install test dependencies
|
||||
run: python -m pip install --disable-pip-version-check -r requirements-test.txt
|
||||
# Mot file duy nhat: requirements-test.txt cu chi co pytest, nhung
|
||||
# 64/108 file test dung widget that (20 file import PySide6 thang o dau
|
||||
# file, khong co bao ve) nen no van phai keo ve gan nhu ca danh sach
|
||||
# runtime. Cai rieng file kia thi pytest chet ngay luc thu thap test.
|
||||
- name: Install dependencies
|
||||
run: python -m pip install --disable-pip-version-check -r requirements.txt
|
||||
|
||||
- name: Check Python syntax
|
||||
run: |
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ Prefer the existing lightweight Conventional Commit prefixes: `feat:`, `fix:`, `
|
||||
Run the application from the parent directory with `python -m cowork_local`. The current reliable test command is:
|
||||
|
||||
```bash
|
||||
python -m pip install -r requirements-test.txt
|
||||
python -m pip install -r requirements.txt
|
||||
python -m pytest tests -q
|
||||
```
|
||||
|
||||
|
||||
@@ -59,10 +59,16 @@ python -m cowork_local
|
||||
|
||||
### 3. Run Automated Tests
|
||||
```bash
|
||||
python -m pip install -r requirements-test.txt
|
||||
python -m pip install -r requirements.txt
|
||||
pytest -q
|
||||
```
|
||||
|
||||
There is one requirements file, not a runtime/test pair. A separate test file
|
||||
would hold only `pytest`: 64 of the 108 test modules build real widgets, and 20
|
||||
of them import PySide6 unguarded at module scope, so it would have to pull in
|
||||
almost the whole runtime list anyway — two files for one near-identical list is
|
||||
just a second place for the pins to drift.
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ CASAN Quality Gate & Verification
|
||||
|
||||
+20
-20
@@ -27,30 +27,30 @@ _current = DEFAULT_LANGUAGE
|
||||
_listeners: List[Callable[[], None]] = []
|
||||
|
||||
# key -> {"en": ..., "ja": ..., "vi": ...}
|
||||
from . import i18n_login_dialog as _i18n_login_dialog
|
||||
from . import i18n_sidebar as _i18n_sidebar
|
||||
from . import i18n_composer as _i18n_composer
|
||||
from . import i18n_hint as _i18n_hint
|
||||
from . import i18n_cowork_tab as _i18n_cowork_tab
|
||||
from . import i18n_settings_dialog as _i18n_settings_dialog
|
||||
from . import i18n_skills_dialog as _i18n_skills_dialog
|
||||
from . import i18n_libreoffice_view as _i18n_libreoffice_view
|
||||
from . import i18n_agents_admin_tab as _i18n_agents_admin_tab
|
||||
from . import i18n_monitoring_overview as _i18n_monitoring_overview
|
||||
from . import login_dialog as _login_dialog
|
||||
from . import sidebar as _sidebar
|
||||
from . import composer as _composer
|
||||
from . import hint as _hint
|
||||
from . import cowork_tab as _cowork_tab
|
||||
from . import settings_dialog as _settings_dialog
|
||||
from . import skills_dialog as _skills_dialog
|
||||
from . import libreoffice_view as _libreoffice_view
|
||||
from . import agents_admin_tab as _agents_admin_tab
|
||||
from . import monitoring_overview as _monitoring_overview
|
||||
|
||||
# Gộp theo đúng thứ tự cũ: khoá trùng thì cụm sau thắng, y như khi tất cả
|
||||
# còn nằm chung một dict literal.
|
||||
STRINGS: Dict[str, Dict[str, str]] = {
|
||||
**_i18n_login_dialog.STRINGS,
|
||||
**_i18n_sidebar.STRINGS,
|
||||
**_i18n_composer.STRINGS,
|
||||
**_i18n_hint.STRINGS,
|
||||
**_i18n_cowork_tab.STRINGS,
|
||||
**_i18n_settings_dialog.STRINGS,
|
||||
**_i18n_skills_dialog.STRINGS,
|
||||
**_i18n_libreoffice_view.STRINGS,
|
||||
**_i18n_agents_admin_tab.STRINGS,
|
||||
**_i18n_monitoring_overview.STRINGS,
|
||||
**_login_dialog.STRINGS,
|
||||
**_sidebar.STRINGS,
|
||||
**_composer.STRINGS,
|
||||
**_hint.STRINGS,
|
||||
**_cowork_tab.STRINGS,
|
||||
**_settings_dialog.STRINGS,
|
||||
**_skills_dialog.STRINGS,
|
||||
**_libreoffice_view.STRINGS,
|
||||
**_agents_admin_tab.STRINGS,
|
||||
**_monitoring_overview.STRINGS,
|
||||
}
|
||||
|
||||
|
||||
+1
-14
@@ -4,7 +4,6 @@ rem Cowork-Local BamBOO - cai dat thu vien Python (chay MOT lan)
|
||||
rem
|
||||
rem Cach dung:
|
||||
rem install.bat cai vao moi truong ao rieng (khuyen dung)
|
||||
rem install.bat --dev cai them thu vien de chay test
|
||||
rem install.bat --system cai thang vao Python dang co, khong dung venv
|
||||
rem install.bat --force dung lai moi truong ao tu dau
|
||||
rem
|
||||
@@ -26,13 +25,11 @@ set "APPHOME=%LOCALAPPDATA%\CoworkLocal"
|
||||
set "VENV=%APPHOME%\venv"
|
||||
set "LAUNCHER=%APPHOME%\launcher"
|
||||
|
||||
set "DEV=0"
|
||||
set "USE_SYSTEM=0"
|
||||
set "FORCE=0"
|
||||
|
||||
:parse_args
|
||||
if "%~1"=="" goto args_done
|
||||
if /I "%~1"=="--dev" set "DEV=1" & shift & goto parse_args
|
||||
if /I "%~1"=="--system" set "USE_SYSTEM=1" & shift & goto parse_args
|
||||
if /I "%~1"=="--force" set "FORCE=1" & shift & goto parse_args
|
||||
if /I "%~1"=="-h" goto usage
|
||||
@@ -120,15 +117,6 @@ if errorlevel 1 (
|
||||
goto fail
|
||||
)
|
||||
|
||||
if "%DEV%"=="1" (
|
||||
echo [3/5] Cài thêm thư viện chạy test ^(--dev^)...
|
||||
%PIP% install --disable-pip-version-check -r "%REPO%\requirements-test.txt"
|
||||
if errorlevel 1 (
|
||||
echo [LỖI] Cài thư viện test thất bại.
|
||||
goto fail
|
||||
)
|
||||
)
|
||||
|
||||
rem --------------------------------------------------------------------------
|
||||
rem 4. Lien ket de goi import duoc dung ten
|
||||
rem
|
||||
@@ -188,9 +176,8 @@ exit /b 0
|
||||
|
||||
:usage
|
||||
echo.
|
||||
echo install.bat [--dev] [--system] [--force]
|
||||
echo install.bat [--system] [--force]
|
||||
echo.
|
||||
echo --dev cài thêm thư viện để chạy test ^(pytest, pydantic^)
|
||||
echo --system cài thẳng vào Python đang có, không tạo môi trường ảo
|
||||
echo --force xoá môi trường ảo cũ rồi tạo lại từ đầu
|
||||
echo.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
pydantic>=2,<3
|
||||
pytest>=8,<10
|
||||
@@ -39,3 +39,12 @@ pywin32>=306; sys_platform == "win32" # Office -> PDF, thông báo Outlook
|
||||
# opendataloader-pdf # bộ đọc PDF thay thế — KHÔNG cài sẵn có chủ ý:
|
||||
# # application/workspaces/graph_index_service.py tự cài
|
||||
# # khi cần, qua core/deps.py::ensure_module.
|
||||
|
||||
# --- Chạy test ---
|
||||
# Gộp vào đây thay vì để riêng requirements-test.txt: file kia chỉ có đúng
|
||||
# `pytest`, mà 64/108 file test dựng widget thật nên nó vẫn phải kéo về gần
|
||||
# như toàn bộ danh sách trên. Hai file cho một danh sách gần trùng nhau chỉ
|
||||
# tạo thêm một chỗ để lệch phiên bản.
|
||||
#
|
||||
# Người dùng cuối cài thừa pytest vài MB — đổi lại chỉ còn MỘT file phải nhớ.
|
||||
pytest>=8,<10
|
||||
|
||||
@@ -40,6 +40,10 @@ if hasattr(sys.stdout, "reconfigure"):
|
||||
DEFAULT_TARGET_DIRS = [
|
||||
"domain", "application", "infrastructure", "presentation",
|
||||
"ui", "core", "providers", "security", "mcp_servers",
|
||||
# ``i18n/`` và ``theme/`` từng là 13 file rời nằm thẳng ở thư mục gốc nên
|
||||
# được quét theo diện "module gốc"; gom vào gói rồi thì phải khai ở đây,
|
||||
# không thì chúng lặng lẽ tuột khỏi tầm quét.
|
||||
"i18n", "theme",
|
||||
]
|
||||
DEFAULT_MAX_LINES = 400
|
||||
|
||||
@@ -60,7 +64,7 @@ SCAN_ROOT_MODULES = True
|
||||
#: đúng là tách file.
|
||||
LEGACY_ALLOWANCE = {
|
||||
"ui/workspace_tab.py": 566,
|
||||
"ui/widgets.py": 505,
|
||||
"ui/widgets.py": 466,
|
||||
"ui/task_editor_dialog.py": 627,
|
||||
"ui/accounts_tab.py": 559,
|
||||
"core/skills.py": 405,
|
||||
|
||||
@@ -87,12 +87,14 @@ def source() -> dict[str, str]:
|
||||
|
||||
|
||||
def test_template_exposes_exactly_three_provider_neutral_tools() -> None:
|
||||
# The MCP SDK is a RUNTIME dependency (requirements.txt) and is deliberately
|
||||
# absent from requirements-test.txt, which is all CI installs. Importing it at
|
||||
# module scope aborted collection for the ENTIRE suite, so the guard lives here,
|
||||
# inside the only test that touches the SDK. Guarding per-test rather than
|
||||
# per-module keeps the other cases -- pure-Python contract checks that need no
|
||||
# SDK -- running on CI instead of silently skipping with it.
|
||||
# Importing the MCP SDK at module scope aborted collection for the ENTIRE
|
||||
# suite whenever the SDK was missing, so the guard lives here, inside the only
|
||||
# test that touches it. Guarding per-test rather than per-module keeps the
|
||||
# other cases -- pure-Python contract checks that need no SDK -- running
|
||||
# instead of silently skipping with it.
|
||||
#
|
||||
# ``mcp`` is in requirements.txt, so a correctly installed checkout runs this
|
||||
# test for real; the guard only covers an environment installed by hand.
|
||||
types = pytest.importorskip("mcp.types")
|
||||
|
||||
assert set(TOOL_NAMES) == EXPECTED_TOOLS
|
||||
|
||||
@@ -34,10 +34,10 @@ original value, so the deviation is auditable rather than silent.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from .theme_palettes import ( # noqa: F401 — giữ đường vào cũ
|
||||
from .palettes import ( # noqa: F401 — giữ đường vào cũ
|
||||
DARK, LIGHT, Palette, _chevron_asset, _FONT, _MONO, _PALETTES,
|
||||
)
|
||||
from .theme_qss import _TEMPLATE
|
||||
from .qss import _TEMPLATE
|
||||
|
||||
from dataclasses import dataclass, asdict
|
||||
from string import Template
|
||||
@@ -4,7 +4,7 @@ Tách khỏi ``theme.py`` vì nó là **dữ liệu**, không phải logic: mộ
|
||||
``string.Template`` mà ``stylesheet()`` thay biến vào. Để chung thì mỗi lần
|
||||
muốn sửa một hàm nhỏ trong theme.py lại phải cuộn qua 470 dòng CSS.
|
||||
|
||||
Sửa màu thì sang ``theme_palettes.py``; ở đây chỉ sửa hình dạng và khoảng cách.
|
||||
Sửa màu thì sang ``theme/palettes.py``; ở đây chỉ sửa hình dạng và khoảng cách.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -12,7 +12,7 @@ from dataclasses import dataclass, asdict
|
||||
from string import Template
|
||||
|
||||
|
||||
from .theme_qss_controls import QSS_CONTROLS
|
||||
from .qss_controls import QSS_CONTROLS
|
||||
|
||||
_QSS_SHELL = """
|
||||
/* ---- reset ------------------------------------------------------------ */
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Nửa sau của khuôn QSS: bề mặt, tab, ô nhập, nút, badge, log.
|
||||
|
||||
Cắt đôi khuôn QSS đúng mạch của chính nó: ``theme_qss.py`` giữ phần vỏ
|
||||
Cắt đôi khuôn QSS đúng mạch của chính nó: ``theme/qss.py`` giữ phần vỏ
|
||||
(reset + shell: thanh rail, khung chính), file này giữ phần điều khiển.
|
||||
Hai nửa được nối lại trong ``theme_qss.py``.
|
||||
Hai nửa được nối lại trong ``theme/qss.py``.
|
||||
|
||||
Sửa màu thì sang ``theme_palettes.py``; ở đây chỉ sửa hình dạng và khoảng cách.
|
||||
Sửa màu thì sang ``theme/palettes.py``; ở đây chỉ sửa hình dạng và khoảng cách.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -26,7 +26,7 @@ class SegmentedControl(QWidget):
|
||||
|
||||
currentIndexChanged = Signal(int)
|
||||
|
||||
#: Độ đậm mà ``theme_qss.py`` áp cho nút đang chọn
|
||||
#: Độ đậm mà ``theme/qss.py`` áp cho nút đang chọn
|
||||
#: (``QPushButton#segItem:checked { font-weight: 600 }``). Đổi ở QSS thì
|
||||
#: phải đổi cả ở đây, nếu không chữ lại bị cắt.
|
||||
_CHECKED_WEIGHT = QFont.DemiBold
|
||||
|
||||
Reference in New Issue
Block a user