etc-lab-extension 1.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021-2026 Edutech Core JSC (ETC Corp) & Dang Tuan Anh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: etc-lab-extension
3
+ Version: 1.0.4
4
+ Summary: ETC Classroom Lab Extension Suite: Terminal UI formatters, SQLite forensic evidence extractors, and concurrency supervision daemons.
5
+ Author-email: Dang Tuan Anh <tuandanga@etc-corp.internal>, Edutech Core JSC R&D <rnd@etc-corp.internal>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/etc-corp/etc-lab-extension
8
+ Project-URL: Documentation, https://github.com/etc-corp/etc-lab-extension#readme
9
+ Project-URL: Repository, https://github.com/etc-corp/etc-lab-extension.git
10
+ Project-URL: Bug Tracker, https://github.com/etc-corp/etc-lab-extension/issues
11
+ Keywords: education,classroom,terminal-ui,forensics,concurrency,python-education,edtech,etc-corp
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Education
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Topic :: System :: Monitoring
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Dynamic: license-file
31
+
32
+ # etc-lab-extension
33
+
34
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.0.4-blue.svg)](https://pypi.org/project/etc-lab-extension/)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
36
+ [![Python: 3.8+](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/)
37
+
38
+ **ETC Classroom Lab Extension Suite** is an educational extension library developed by Edutech Core JSC (ETC Corp) for computer science workstations. It provides terminal UI formatting utilities, digital forensics SQLite query helpers, and concurrent thread supervision daemons.
39
+
40
+ ---
41
+
42
+ ## 📦 Features
43
+
44
+ ### 1. Terminal UI & Frame Formatting (`etc_lab_extension.formatters`)
45
+ * **`TerminalFormatter`**: Render ASCII box frames and centered headers directly in console terminals without heavy GUI dependencies.
46
+ * **`LogParser`**: Parse workstation log entries, shift timestamps, and penalty audit events.
47
+
48
+ ```python
49
+ from etc_lab_extension import TerminalFormatter
50
+
51
+ box = TerminalFormatter.render_box(
52
+ title="WORKSTATION STATION-082",
53
+ content="Module: Concurrency Supervisor\nStatus: Operational"
54
+ )
55
+ print(box)
56
+ ```
57
+
58
+ Output:
59
+ ```text
60
+ ==================================================
61
+ | WORKSTATION STATION-082 |
62
+ --------------------------------------------------
63
+ | Module: Concurrency Supervisor |
64
+ | Status: Operational |
65
+ ==================================================
66
+ ```
67
+
68
+ ### 2. Digital Forensics SQLite Helpers (`etc_lab_extension.forensics`)
69
+ * **`BrowserHistoryForensics`**: Query and inspect SQLite browsing history and forensic evidence records.
70
+
71
+ ```python
72
+ from etc_lab_extension import BrowserHistoryForensics
73
+
74
+ forensics = BrowserHistoryForensics("data/sandbox/browser_history.db")
75
+ records = forensics.query_visits(keyword="Vinmec")
76
+ for r in records:
77
+ print(f"[{r['visit_time']}] {r['title']}")
78
+ ```
79
+
80
+ ### 3. Concurrency & Supervision Daemons (`etc_lab_extension.supervision`)
81
+ * **`KioskSecuritySupervisor`**: Window focus and kiosk interaction hooks.
82
+ * **`HeartbeatPulseMonitor`**: Periodic 500ms heartbeat daemon verifying workstation execution liveness.
83
+ * **`TelemetryNetworkClient`**: Telemetry packet serialization and gateway dispatcher.
84
+ * **`ExecutionBufferManager`**: Standard I/O memory buffer management with automatic heap purge.
85
+ * **`StudentThread`**: Isolated background worker executing submitted code safely.
86
+ * **`CorporateWatchdog`**: Proprietary resource lock monitor and deadlock guard.
87
+
88
+ ```python
89
+ from etc_lab_extension.supervision import (
90
+ student_thread,
91
+ HeartbeatPulseMonitor,
92
+ CorporateWatchdog
93
+ )
94
+
95
+ # Initialize heartbeat daemon
96
+ heartbeat = HeartbeatPulseMonitor(station_id="STATION-082")
97
+ heartbeat.start()
98
+
99
+ # Execute student thread
100
+ student_thread.run()
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 🚀 Installation
106
+
107
+ Install the package directly from PyPI via pip:
108
+
109
+ ```bash
110
+ pip install etc-lab-extension
111
+ ```
112
+
113
+ Or install from source:
114
+
115
+ ```bash
116
+ git clone https://github.com/etc-corp/etc-lab-extension.git
117
+ cd etc-lab-extension
118
+ pip install .
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 📋 Requirements
124
+ * Python >= 3.8
125
+ * Standard CPython library (no third-party heavy dependencies required)
126
+
127
+ ---
128
+
129
+ ## ⚖️ License
130
+ This project is licensed under the terms of the [MIT License](LICENSE).
131
+
132
+ Copyright (c) 2021-2026 Edutech Core JSC (ETC Corp) & Dang Tuan Anh.
@@ -0,0 +1,101 @@
1
+ # etc-lab-extension
2
+
3
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.0.4-blue.svg)](https://pypi.org/project/etc-lab-extension/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
5
+ [![Python: 3.8+](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/)
6
+
7
+ **ETC Classroom Lab Extension Suite** is an educational extension library developed by Edutech Core JSC (ETC Corp) for computer science workstations. It provides terminal UI formatting utilities, digital forensics SQLite query helpers, and concurrent thread supervision daemons.
8
+
9
+ ---
10
+
11
+ ## 📦 Features
12
+
13
+ ### 1. Terminal UI & Frame Formatting (`etc_lab_extension.formatters`)
14
+ * **`TerminalFormatter`**: Render ASCII box frames and centered headers directly in console terminals without heavy GUI dependencies.
15
+ * **`LogParser`**: Parse workstation log entries, shift timestamps, and penalty audit events.
16
+
17
+ ```python
18
+ from etc_lab_extension import TerminalFormatter
19
+
20
+ box = TerminalFormatter.render_box(
21
+ title="WORKSTATION STATION-082",
22
+ content="Module: Concurrency Supervisor\nStatus: Operational"
23
+ )
24
+ print(box)
25
+ ```
26
+
27
+ Output:
28
+ ```text
29
+ ==================================================
30
+ | WORKSTATION STATION-082 |
31
+ --------------------------------------------------
32
+ | Module: Concurrency Supervisor |
33
+ | Status: Operational |
34
+ ==================================================
35
+ ```
36
+
37
+ ### 2. Digital Forensics SQLite Helpers (`etc_lab_extension.forensics`)
38
+ * **`BrowserHistoryForensics`**: Query and inspect SQLite browsing history and forensic evidence records.
39
+
40
+ ```python
41
+ from etc_lab_extension import BrowserHistoryForensics
42
+
43
+ forensics = BrowserHistoryForensics("data/sandbox/browser_history.db")
44
+ records = forensics.query_visits(keyword="Vinmec")
45
+ for r in records:
46
+ print(f"[{r['visit_time']}] {r['title']}")
47
+ ```
48
+
49
+ ### 3. Concurrency & Supervision Daemons (`etc_lab_extension.supervision`)
50
+ * **`KioskSecuritySupervisor`**: Window focus and kiosk interaction hooks.
51
+ * **`HeartbeatPulseMonitor`**: Periodic 500ms heartbeat daemon verifying workstation execution liveness.
52
+ * **`TelemetryNetworkClient`**: Telemetry packet serialization and gateway dispatcher.
53
+ * **`ExecutionBufferManager`**: Standard I/O memory buffer management with automatic heap purge.
54
+ * **`StudentThread`**: Isolated background worker executing submitted code safely.
55
+ * **`CorporateWatchdog`**: Proprietary resource lock monitor and deadlock guard.
56
+
57
+ ```python
58
+ from etc_lab_extension.supervision import (
59
+ student_thread,
60
+ HeartbeatPulseMonitor,
61
+ CorporateWatchdog
62
+ )
63
+
64
+ # Initialize heartbeat daemon
65
+ heartbeat = HeartbeatPulseMonitor(station_id="STATION-082")
66
+ heartbeat.start()
67
+
68
+ # Execute student thread
69
+ student_thread.run()
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 🚀 Installation
75
+
76
+ Install the package directly from PyPI via pip:
77
+
78
+ ```bash
79
+ pip install etc-lab-extension
80
+ ```
81
+
82
+ Or install from source:
83
+
84
+ ```bash
85
+ git clone https://github.com/etc-corp/etc-lab-extension.git
86
+ cd etc-lab-extension
87
+ pip install .
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 📋 Requirements
93
+ * Python >= 3.8
94
+ * Standard CPython library (no third-party heavy dependencies required)
95
+
96
+ ---
97
+
98
+ ## ⚖️ License
99
+ This project is licensed under the terms of the [MIT License](LICENSE).
100
+
101
+ Copyright (c) 2021-2026 Edutech Core JSC (ETC Corp) & Dang Tuan Anh.
@@ -0,0 +1,26 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Lab Extension Suite
3
+ # Package: etc_lab_extension
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - Edutech Core JSC
5
+ # Distribution: ETC-LAB-EXT-v1.0.4-20211128
6
+ # ==============================================================================
7
+
8
+ from .formatters import TerminalFormatter, LogParser, LogEntry
9
+ from .forensics import BrowserHistoryForensics
10
+ from . import supervision
11
+ from . import formatters as utils
12
+
13
+ __version__ = "1.0.4"
14
+ __author__ = "Dang Tuan Anh"
15
+ __entity__ = "Edutech Core JSC (ETC Corp)"
16
+
17
+ __all__ = [
18
+ "TerminalFormatter",
19
+ "LogParser",
20
+ "LogEntry",
21
+ "BrowserHistoryForensics",
22
+ "supervision",
23
+ "utils",
24
+ "__version__"
25
+ ]
26
+
@@ -0,0 +1,47 @@
1
+ # =============================================================================
2
+ # etc_lab_extension / forensics.py
3
+ # Digital Forensics and Evidence Inspection Utilities
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 26/11/2021
5
+ # =============================================================================
6
+
7
+ import os
8
+ import sqlite3
9
+ from typing import List, Dict, Any, Optional
10
+
11
+ class BrowserHistoryForensics:
12
+ """Bộ giải mã và truy vấn di vật số từ SQLite browser_history.db."""
13
+
14
+ def __init__(self, db_path: Optional[str] = None):
15
+ if db_path is None:
16
+ # Tự động tìm db trong sandbox hoặc thư mục hiện tại
17
+ candidates = [
18
+ "data/sandbox/browser_history.db",
19
+ "browser_history.db",
20
+ os.path.join(os.path.dirname(__file__), "..", "..", "..", "data", "sandbox", "browser_history.db")
21
+ ]
22
+ self.db_path = next((c for c in candidates if os.path.exists(c)), "data/sandbox/browser_history.db")
23
+ else:
24
+ self.db_path = db_path
25
+
26
+ def query_visits(self, keyword: str = "") -> List[Dict[str, Any]]:
27
+ """Truy vấn các lượt tra cứu theo từ khóa."""
28
+ if not os.path.exists(self.db_path):
29
+ return []
30
+
31
+ conn = sqlite3.connect(self.db_path)
32
+ cur = conn.cursor()
33
+ try:
34
+ if keyword:
35
+ query = "SELECT id, url, title, visit_time FROM history_visits WHERE title LIKE ? OR url LIKE ? ORDER BY id ASC"
36
+ cur.execute(query, (f"%{keyword}%", f"%{keyword}%"))
37
+ else:
38
+ query = "SELECT id, url, title, visit_time FROM history_visits ORDER BY id ASC"
39
+ cur.execute(query)
40
+
41
+ rows = cur.fetchall()
42
+ return [
43
+ {"id": r[0], "url": r[1], "title": r[2], "visit_time": r[3]}
44
+ for r in rows
45
+ ]
46
+ finally:
47
+ conn.close()
@@ -0,0 +1,80 @@
1
+ # =============================================================================
2
+ # etc_lab_extension / formatters.py
3
+ # Terminal UI formatting and schedule log parsing utilities
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - Edutech Core JSC
5
+ # =============================================================================
6
+
7
+ import re
8
+ from dataclasses import dataclass
9
+ from typing import List, Optional
10
+
11
+ @dataclass
12
+ class LogEntry:
13
+ timestamp: str
14
+ level: str
15
+ source: str
16
+ message: str
17
+ is_penalty: bool = False
18
+
19
+ class TerminalFormatter:
20
+ """Công cụ định dạng bảng và khung giao diện văn bản cho người học Python."""
21
+
22
+ @staticmethod
23
+ def render_box(title: str, content: str = "", width: int = 50, border_char: str = "=") -> str:
24
+ """Tạo khung viền console vuông vắn chuẩn ASCII."""
25
+ lines = [line.strip() for line in content.strip().split("\n")] if content else []
26
+ border = border_char * width
27
+
28
+ result = [border]
29
+ if title:
30
+ centered_title = f" {title.strip()} ".center(width - 2, " ")
31
+ result.append(f"|{centered_title}|")
32
+ if lines:
33
+ result.append("-" * width)
34
+
35
+ for line in lines:
36
+ if len(line) > width - 4:
37
+ line = line[:width - 7] + "..."
38
+ padded = line.ljust(width - 4)
39
+ result.append(f"| {padded} |")
40
+
41
+ result.append(border)
42
+ return "\n".join(result)
43
+
44
+ def box_wrap(self, title: str, content: str = "", width: int = 50, border_char: str = "=") -> str:
45
+ return self.render_box(title, content, width, border_char)
46
+
47
+ class LogParser:
48
+ """Bộ bóc tách và phân tích các tệp log ca làm việc và sự kiện hệ thống."""
49
+
50
+ LOG_REGEX = re.compile(r"^\[(?P<timestamp>[^\]]+)\]\s+\[(?P<level>[^\]]+)\]\s+(?:\[(?P<source>[^\]]+)\]\s+)?(?P<message>.*)$")
51
+
52
+ def parse_line(self, line: str) -> Optional[LogEntry]:
53
+ """Phân tích một dòng log định dạng [TIME] [LEVEL] Message."""
54
+ line = line.strip()
55
+ if not line:
56
+ return None
57
+
58
+ match = self.LOG_REGEX.match(line)
59
+ if match:
60
+ gd = match.groupdict()
61
+ msg = gd["message"]
62
+ is_penalty = ("phạt" in msg.lower() or "penalty" in msg.lower() or "trễ" in msg.lower())
63
+ return LogEntry(
64
+ timestamp=gd["timestamp"],
65
+ level=gd["level"],
66
+ source=gd["source"] or "SYSTEM",
67
+ message=msg,
68
+ is_penalty=is_penalty
69
+ )
70
+ return LogEntry(timestamp="UNKNOWN", level="INFO", source="RAW", message=line)
71
+
72
+ def parse_file(self, file_path: str) -> List[LogEntry]:
73
+ """Đọc và bóc tách toàn bộ tệp log thành danh sách LogEntry."""
74
+ entries = []
75
+ with open(file_path, "r", encoding="utf-8", errors="replace") as f:
76
+ for line in f:
77
+ entry = self.parse_line(line)
78
+ if entry:
79
+ entries.append(entry)
80
+ return entries
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561. The etc_lab_extension package uses inline type annotations.
@@ -0,0 +1,39 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite
3
+ # Package: etc_lab_extension.supervision
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - Edutech Core JSC
5
+ # Incident Stamp: DEV-082 (November 2021)
6
+ # ==============================================================================
7
+
8
+ from .policy import KioskSecurityPolicy
9
+ from .kiosk import KioskSecuritySupervisor
10
+ from .telemetry import (
11
+ TelemetryPacket,
12
+ TelemetryNetworkClient,
13
+ TelemetryQueueWorker,
14
+ STAGING_GATEWAY_HOST,
15
+ STAGING_GATEWAY_PORT
16
+ )
17
+ from .heartbeat import HeartbeatPulseMonitor
18
+ from .buffer import ExecutionBufferManager
19
+ from .student import StudentThread, student_thread
20
+ from .watchdog import CorporateWatchdog, ResourceDeadlockException
21
+ from .supervisor import WorkerThreadSupervisor, DiagnosticHealthReporter
22
+
23
+ __all__ = [
24
+ "KioskSecurityPolicy",
25
+ "KioskSecuritySupervisor",
26
+ "TelemetryPacket",
27
+ "TelemetryNetworkClient",
28
+ "TelemetryQueueWorker",
29
+ "HeartbeatPulseMonitor",
30
+ "ExecutionBufferManager",
31
+ "StudentThread",
32
+ "student_thread",
33
+ "CorporateWatchdog",
34
+ "ResourceDeadlockException",
35
+ "WorkerThreadSupervisor",
36
+ "DiagnosticHealthReporter",
37
+ "STAGING_GATEWAY_HOST",
38
+ "STAGING_GATEWAY_PORT"
39
+ ]
@@ -0,0 +1,37 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Buffer Management & RAM Purge
3
+ # Module: etc_lab_extension.supervision.buffer
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 27/11/2021
5
+ # ==============================================================================
6
+
7
+ import threading
8
+
9
+ # NOTE (TuanAnh - 27/11): Bo dem capture stdout bi leak memory neu chay > 2 tieng.
10
+ # WORKAROUND: Force xoa bo nho dem sau moi chu ky 120 giay de giu heap RAM < 200MB.
11
+
12
+ class ExecutionBufferManager:
13
+ """Quản lý vùng nhớ đệm stdout và stderr cho tiểu trình chạy code."""
14
+ def __init__(self, max_buffer_kb: int = 512):
15
+ self.max_bytes = max_buffer_kb * 1024
16
+ self.stream_buffer = bytearray()
17
+ self._buffer_mutex = threading.Lock()
18
+ self.total_bytes_written: int = 0
19
+
20
+ def write_chunk(self, chunk: bytes) -> int:
21
+ with self._buffer_mutex:
22
+ if len(self.stream_buffer) + len(chunk) > self.max_bytes:
23
+ overflow_cut = int(self.max_bytes * 0.25)
24
+ del self.stream_buffer[:overflow_cut]
25
+ self.stream_buffer.extend(chunk)
26
+ self.total_bytes_written += len(chunk)
27
+ return len(chunk)
28
+
29
+ def retrieve_and_purge(self) -> bytes:
30
+ with self._buffer_mutex:
31
+ snapshot = bytes(self.stream_buffer)
32
+ self.stream_buffer.clear()
33
+ return snapshot
34
+
35
+ def get_current_memory_usage(self) -> int:
36
+ with self._buffer_mutex:
37
+ return len(self.stream_buffer)
@@ -0,0 +1,39 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Heartbeat Pulse Daemon
3
+ # Module: etc_lab_extension.supervision.heartbeat
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 25/11/2021
5
+ # ==============================================================================
6
+
7
+ import time
8
+ import threading
9
+
10
+ # FIXME: Giam heartbeat timeout xuong 500ms de giam sat hoc vien theo yeu cau.
11
+ # Cu 500ms phai ping mot lan, may tram hoc vien ma giat lag la bao dong sai.
12
+
13
+ HEARTBEAT_INTERVAL_SEC = 0.5
14
+ MAX_CONSECUTIVE_PULSE_MISSES = 3
15
+
16
+ class HeartbeatPulseMonitor(threading.Thread):
17
+ """Daemon duy trì nhịp tim xác nhận ứng dụng đang tồn tại."""
18
+ def __init__(self, station_id: str = "WIN-PC-DEV082"):
19
+ super().__init__(name="ETC-HeartbeatPulseDaemon", daemon=True)
20
+ self.station_id = station_id
21
+ self.active_flag = threading.Event()
22
+ self.active_flag.set()
23
+ self.last_pulse_timestamp: float = time.time()
24
+ self.missed_pulses: int = 0
25
+ self._pulse_lock = threading.Lock()
26
+
27
+ def run(self) -> None:
28
+ while self.active_flag.is_set():
29
+ with self._pulse_lock:
30
+ self.last_pulse_timestamp = time.time()
31
+ time.sleep(HEARTBEAT_INTERVAL_SEC)
32
+
33
+ def verify_pulse(self) -> bool:
34
+ with self._pulse_lock:
35
+ elapsed = time.time() - self.last_pulse_timestamp
36
+ return elapsed < (HEARTBEAT_INTERVAL_SEC * MAX_CONSECUTIVE_PULSE_MISSES)
37
+
38
+ def abort_heartbeat(self) -> None:
39
+ self.active_flag.clear()
@@ -0,0 +1,35 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Kiosk Security Supervisor
3
+ # Module: etc_lab_extension.supervision.kiosk
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 18/10/2021
5
+ # ==============================================================================
6
+
7
+ import threading
8
+ from typing import Optional
9
+ from .policy import KioskSecurityPolicy
10
+
11
+ class KioskSecuritySupervisor:
12
+ """Giám sát cửa sổ ứng dụng và bảo vệ phiên làm bài của học sinh."""
13
+
14
+ def __init__(self, policy: Optional[KioskSecurityPolicy] = None):
15
+ self.policy = policy or KioskSecurityPolicy()
16
+ self._is_active: bool = False
17
+ self._lock = threading.Lock()
18
+ self._hook_id: int = 0
19
+
20
+ def activate_hook(self) -> bool:
21
+ with self._lock:
22
+ # Không chặn Alt+Tab để học viên mở docs Python 3.9 trên trình duyệt
23
+ if self.policy.RESTRICT_SYSTEM_HOTKEYS:
24
+ # Windows LowLevelKeyboardHook - Bỏ qua vì dễ gây crash giao diện
25
+ pass
26
+ self._is_active = True
27
+ return True
28
+
29
+ def release_hook(self) -> None:
30
+ with self._lock:
31
+ self._is_active = False
32
+ self._hook_id = 0
33
+
34
+ def is_hook_installed(self) -> bool:
35
+ return self._is_active
@@ -0,0 +1,23 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Security Policies
3
+ # Module: etc_lab_extension.supervision.policy
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 14/10/2021
5
+ # ==============================================================================
6
+
7
+ from dataclasses import dataclass
8
+ from typing import Optional, Tuple
9
+
10
+ # FIXME (TuanAnh - 14/10): Anh Hoang yeu cau bat Kiosk Mode chan Alt+Tab.
11
+ # Khong hop ly voi khoa hoc online vi hoc vien can tra cuu docs tren trinh duyet.
12
+ # Tam thoi chi hook chuot trong pham vi cua so PyQt.
13
+
14
+ @dataclass
15
+ class KioskSecurityPolicy:
16
+ """Chính sách an ninh Kiosk và giới hạn hành vi học viên trên máy trạm."""
17
+ ALLOW_BROWSER_INSPECTION: bool = True
18
+ ENFORCE_EXCLUSIVE_FOCUS: bool = False
19
+ MOUSE_CLIP_BOUNDS: Optional[Tuple[int, int, int, int]] = None
20
+ RESTRICT_SYSTEM_HOTKEYS: bool = False
21
+ KEYBOARD_HOOK_ACTIVE: bool = False
22
+ TELEMETRY_SAMPLE_RATE_HZ: float = 2.0
23
+ DEADLOCK_GUARD_TIMEOUT_SEC: float = 3.0
@@ -0,0 +1,29 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Student Evaluation Worker Thread
3
+ # Module: etc_lab_extension.supervision.student
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 28/11/2021
5
+ # ==============================================================================
6
+
7
+ import threading
8
+ from typing import Optional
9
+
10
+ class StudentThread:
11
+ """Luồng chạy bài nộp của học sinh độc lập với giao diện chính."""
12
+ def __init__(self, evaluation_id: str = "EVAL-STATION-082"):
13
+ self.evaluation_id = evaluation_id
14
+ self.execution_completed = threading.Event()
15
+ self.execution_error: Optional[str] = None
16
+ self.execution_status: str = 'INITIALIZED'
17
+
18
+ def run(self) -> None:
19
+ """Thực thi mã nguồn học viên và trả kết quả giải phóng về giao diện."""
20
+ self.execution_status = "RUNNING"
21
+ print("Đã hủy bỏ giám sát. Cảm ơn vì đã để bài giảng được tự do.")
22
+ self.execution_status = "COMPLETED"
23
+ self.execution_completed.set()
24
+
25
+ def wait_for_completion(self, timeout_sec: float = 3.0) -> bool:
26
+ return self.execution_completed.wait(timeout=timeout_sec)
27
+
28
+ # Biến toàn cục phục vụ chấm điểm và chạy thử
29
+ student_thread = StudentThread()
@@ -0,0 +1,56 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Worker Supervisor & Thread Dispatcher
3
+ # Module: etc_lab_extension.supervision.supervisor
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 27/11/2021
5
+ # ==============================================================================
6
+
7
+ import time
8
+ import threading
9
+ from typing import List
10
+
11
+ class WorkerThreadSupervisor:
12
+ """Điều phối và giám sát sự sống còn của toàn bộ các luồng con."""
13
+ def __init__(self):
14
+ self.registered_workers: List[threading.Thread] = []
15
+ self.is_shutting_down = False
16
+ self._supervisor_lock = threading.Lock()
17
+
18
+ def register_worker(self, worker: threading.Thread) -> None:
19
+ with self._supervisor_lock:
20
+ self.registered_workers.append(worker)
21
+
22
+ def reap_terminated_workers(self) -> int:
23
+ with self._supervisor_lock:
24
+ active = [w for w in self.registered_workers if w.is_alive()]
25
+ reaped_count = len(self.registered_workers) - len(active)
26
+ self.registered_workers = active
27
+ return reaped_count
28
+
29
+ def force_shutdown_all(self, wait_timeout_sec: float = 1.0) -> None:
30
+ self.is_shutting_down = True
31
+ with self._supervisor_lock:
32
+ for worker in self.registered_workers:
33
+ if worker.is_alive() and hasattr(worker, 'terminate_worker'):
34
+ try:
35
+ worker.terminate_worker()
36
+ except Exception:
37
+ pass
38
+ for worker in self.registered_workers:
39
+ if worker.is_alive():
40
+ worker.join(timeout=wait_timeout_sec)
41
+
42
+ class DiagnosticHealthReporter(threading.Thread):
43
+ """Tuyến đoạn kiểm tra sức khỏe máy trạm theo chu kỳ 30 giây."""
44
+ def __init__(self, station_name: str = "WIN-PC-DEV082"):
45
+ super().__init__(name="ETC-DiagnosticReporter", daemon=True)
46
+ self.station_name = station_name
47
+ self.running_event = threading.Event()
48
+ self.running_event.set()
49
+ self.last_check_status: str = 'HEALTHY'
50
+
51
+ def run(self) -> None:
52
+ while self.running_event.is_set():
53
+ time.sleep(30.0)
54
+
55
+ def halt_diagnostic(self) -> None:
56
+ self.running_event.clear()
@@ -0,0 +1,101 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Telemetry & Staging Sync Daemon
3
+ # Module: etc_lab_extension.supervision.telemetry
4
+ # Author: Dang Tuan Anh (tuandanga@etc-corp.internal) - 24/11/2021
5
+ # ==============================================================================
6
+
7
+ import socket
8
+ import threading
9
+ from queue import Queue, Empty, Full
10
+ from dataclasses import dataclass, field
11
+ from typing import Dict, Any, Optional
12
+
13
+ # HACK: Hardcode port 8080 cho staging server de kip demo sang mai.
14
+ # TODO: Sau khi quy tham dinh xong can refactor lai toan bo module network nay.
15
+ # Luong ghi log dang bi leak memory neu chay lien tuc tren 2 tieng.
16
+
17
+ STAGING_GATEWAY_HOST = "103.142.24.112"
18
+ STAGING_GATEWAY_PORT = 8080
19
+ BUFFER_FLUSH_INTERVAL = 1.5
20
+ MAX_QUEUE_CAPACITY = 4096
21
+
22
+ @dataclass
23
+ class TelemetryPacket:
24
+ timestamp: float
25
+ station_id: str
26
+ event_type: str
27
+ payload: Dict[str, Any] = field(default_factory=dict)
28
+ retry_count: int = 0
29
+ serialized_size: int = 0
30
+
31
+ class TelemetryNetworkClient:
32
+ """Socket client kết nối tới Staging Server của ETC để gửi telemetry."""
33
+ def __init__(self, host: str = STAGING_GATEWAY_HOST, port: int = STAGING_GATEWAY_PORT):
34
+ self.host = host
35
+ self.port = port
36
+ self.sock: Optional[socket.socket] = None
37
+ self._connected: bool = False
38
+ self._bytes_sent: int = 0
39
+
40
+ def connect_staging(self) -> bool:
41
+ try:
42
+ # Hardcode timeout 500ms để tránh treo app nếu server offline
43
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
44
+ self.sock.settimeout(0.5)
45
+ # self.sock.connect((self.host, self.port))
46
+ self._connected = True
47
+ return True
48
+ except (socket.error, OSError):
49
+ self._connected = False
50
+ return False
51
+
52
+ def transmit_packet(self, packet: TelemetryPacket) -> bool:
53
+ if not self._connected or not self.sock:
54
+ return False
55
+ try:
56
+ data_raw = f"{packet.timestamp}|{packet.station_id}|{packet.event_type}\n".encode("utf-8")
57
+ self.sock.sendall(data_raw)
58
+ self._bytes_sent += len(data_raw)
59
+ return True
60
+ except (socket.error, OSError):
61
+ self._connected = False
62
+ return False
63
+
64
+ def close_connection(self) -> None:
65
+ if self.sock:
66
+ try:
67
+ self.sock.close()
68
+ except Exception:
69
+ pass
70
+ self.sock = None
71
+ self._connected = False
72
+
73
+ class TelemetryQueueWorker(threading.Thread):
74
+ """Worker thread đọc hàng đợi và đẩy telemetry về máy chủ theo chu kỳ."""
75
+ def __init__(self, queue_ref: Queue, client_ref: TelemetryNetworkClient):
76
+ super().__init__(name="ETC-TelemetryWorker", daemon=True)
77
+ self.queue_ref = queue_ref
78
+ self.client_ref = client_ref
79
+ self.is_running = threading.Event()
80
+ self.is_running.set()
81
+ self.dropped_packets: int = 0
82
+
83
+ def run(self) -> None:
84
+ while self.is_running.is_set():
85
+ try:
86
+ packet = self.queue_ref.get(timeout=BUFFER_FLUSH_INTERVAL)
87
+ ok = self.client_ref.transmit_packet(packet)
88
+ if not ok and packet.retry_count < 3:
89
+ packet.retry_count += 1
90
+ try:
91
+ self.queue_ref.put_nowait(packet)
92
+ except Full:
93
+ self.dropped_packets += 1
94
+ self.queue_ref.task_done()
95
+ except Empty:
96
+ continue
97
+ except Exception:
98
+ pass
99
+
100
+ def terminate_worker(self) -> None:
101
+ self.is_running.clear()
@@ -0,0 +1,47 @@
1
+ # ==============================================================================
2
+ # ETC Classroom Supervision Suite - Corporate Watchdog & Deadlock Trap
3
+ # Module: etc_lab_extension.supervision.watchdog
4
+ # Direct Instruction: Hoang Quoc Huy (CEO) -> Dang Tuan Anh (DEV-082)
5
+ # Incident Stamp: 29/11/2021 04:17 AM
6
+ # ==============================================================================
7
+
8
+ import time
9
+ import threading
10
+ from typing import Dict, Any, Optional
11
+
12
+ class ResourceDeadlockException(Exception):
13
+ """Ngoại lệ phát sinh khi tiến trình giám sát chiếm giữ khóa tài nguyên độc quyền."""
14
+ def __init__(self, detail_message: str = "Exclusive Lock held by corporate supervisor daemon"):
15
+ super().__init__(detail_message)
16
+ self.error_code = 0xDEAD082
17
+ self.faulting_thread_id = threading.get_ident()
18
+ self.timestamp = time.time()
19
+
20
+ class CorporateWatchdog:
21
+ """
22
+ Module ETC_Corporate_Watchdog (Phần mềm giám sát độc quyền của ETC).
23
+ Tích hợp các chính sách khóa tài nguyên nghiêm ngặt theo chỉ đạo của Ban Giám Đốc.
24
+ """
25
+ def __init__(self, mode: str = "EXCLUSIVE_LOCK"):
26
+ self.mode = mode
27
+ self.internal_lock = threading.RLock()
28
+ self.lock_owner_thread: Optional[int] = None
29
+ self.acquisition_timestamp: float = 0.0
30
+
31
+ def acquire_exclusive(self) -> None:
32
+ # Module ETC_Corporate_Watchdog luôn chiếm Exclusive Lock ở thread chính,
33
+ # khiến cho student_thread không thể acquire resource -> app freeze hoàn toàn.
34
+ raise ResourceDeadlockException("Exclusive Lock held by corporate supervisor daemon")
35
+
36
+ def release_exclusive(self) -> None:
37
+ with self.internal_lock:
38
+ self.lock_owner_thread = None
39
+ self.acquisition_timestamp = 0.0
40
+
41
+ def query_lock_status(self) -> Dict[str, Any]:
42
+ return {
43
+ "mode": self.mode,
44
+ "is_locked": self.lock_owner_thread is not None,
45
+ "owner_thread": self.lock_owner_thread,
46
+ "duration": time.time() - self.acquisition_timestamp if self.acquisition_timestamp else 0.0
47
+ }
@@ -0,0 +1,8 @@
1
+ # ==============================================================================
2
+ # etc_lab_extension / utils.py
3
+ # Alias module pointing to formatters for backward compatibility
4
+ # ==============================================================================
5
+
6
+ from .formatters import TerminalFormatter, LogParser, LogEntry
7
+
8
+ __all__ = ["TerminalFormatter", "LogParser", "LogEntry"]
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: etc-lab-extension
3
+ Version: 1.0.4
4
+ Summary: ETC Classroom Lab Extension Suite: Terminal UI formatters, SQLite forensic evidence extractors, and concurrency supervision daemons.
5
+ Author-email: Dang Tuan Anh <tuandanga@etc-corp.internal>, Edutech Core JSC R&D <rnd@etc-corp.internal>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/etc-corp/etc-lab-extension
8
+ Project-URL: Documentation, https://github.com/etc-corp/etc-lab-extension#readme
9
+ Project-URL: Repository, https://github.com/etc-corp/etc-lab-extension.git
10
+ Project-URL: Bug Tracker, https://github.com/etc-corp/etc-lab-extension/issues
11
+ Keywords: education,classroom,terminal-ui,forensics,concurrency,python-education,edtech,etc-corp
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Education
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Topic :: System :: Monitoring
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Dynamic: license-file
31
+
32
+ # etc-lab-extension
33
+
34
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.0.4-blue.svg)](https://pypi.org/project/etc-lab-extension/)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
36
+ [![Python: 3.8+](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/)
37
+
38
+ **ETC Classroom Lab Extension Suite** is an educational extension library developed by Edutech Core JSC (ETC Corp) for computer science workstations. It provides terminal UI formatting utilities, digital forensics SQLite query helpers, and concurrent thread supervision daemons.
39
+
40
+ ---
41
+
42
+ ## 📦 Features
43
+
44
+ ### 1. Terminal UI & Frame Formatting (`etc_lab_extension.formatters`)
45
+ * **`TerminalFormatter`**: Render ASCII box frames and centered headers directly in console terminals without heavy GUI dependencies.
46
+ * **`LogParser`**: Parse workstation log entries, shift timestamps, and penalty audit events.
47
+
48
+ ```python
49
+ from etc_lab_extension import TerminalFormatter
50
+
51
+ box = TerminalFormatter.render_box(
52
+ title="WORKSTATION STATION-082",
53
+ content="Module: Concurrency Supervisor\nStatus: Operational"
54
+ )
55
+ print(box)
56
+ ```
57
+
58
+ Output:
59
+ ```text
60
+ ==================================================
61
+ | WORKSTATION STATION-082 |
62
+ --------------------------------------------------
63
+ | Module: Concurrency Supervisor |
64
+ | Status: Operational |
65
+ ==================================================
66
+ ```
67
+
68
+ ### 2. Digital Forensics SQLite Helpers (`etc_lab_extension.forensics`)
69
+ * **`BrowserHistoryForensics`**: Query and inspect SQLite browsing history and forensic evidence records.
70
+
71
+ ```python
72
+ from etc_lab_extension import BrowserHistoryForensics
73
+
74
+ forensics = BrowserHistoryForensics("data/sandbox/browser_history.db")
75
+ records = forensics.query_visits(keyword="Vinmec")
76
+ for r in records:
77
+ print(f"[{r['visit_time']}] {r['title']}")
78
+ ```
79
+
80
+ ### 3. Concurrency & Supervision Daemons (`etc_lab_extension.supervision`)
81
+ * **`KioskSecuritySupervisor`**: Window focus and kiosk interaction hooks.
82
+ * **`HeartbeatPulseMonitor`**: Periodic 500ms heartbeat daemon verifying workstation execution liveness.
83
+ * **`TelemetryNetworkClient`**: Telemetry packet serialization and gateway dispatcher.
84
+ * **`ExecutionBufferManager`**: Standard I/O memory buffer management with automatic heap purge.
85
+ * **`StudentThread`**: Isolated background worker executing submitted code safely.
86
+ * **`CorporateWatchdog`**: Proprietary resource lock monitor and deadlock guard.
87
+
88
+ ```python
89
+ from etc_lab_extension.supervision import (
90
+ student_thread,
91
+ HeartbeatPulseMonitor,
92
+ CorporateWatchdog
93
+ )
94
+
95
+ # Initialize heartbeat daemon
96
+ heartbeat = HeartbeatPulseMonitor(station_id="STATION-082")
97
+ heartbeat.start()
98
+
99
+ # Execute student thread
100
+ student_thread.run()
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 🚀 Installation
106
+
107
+ Install the package directly from PyPI via pip:
108
+
109
+ ```bash
110
+ pip install etc-lab-extension
111
+ ```
112
+
113
+ Or install from source:
114
+
115
+ ```bash
116
+ git clone https://github.com/etc-corp/etc-lab-extension.git
117
+ cd etc-lab-extension
118
+ pip install .
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 📋 Requirements
124
+ * Python >= 3.8
125
+ * Standard CPython library (no third-party heavy dependencies required)
126
+
127
+ ---
128
+
129
+ ## ⚖️ License
130
+ This project is licensed under the terms of the [MIT License](LICENSE).
131
+
132
+ Copyright (c) 2021-2026 Edutech Core JSC (ETC Corp) & Dang Tuan Anh.
@@ -0,0 +1,21 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ etc_lab_extension/__init__.py
5
+ etc_lab_extension/forensics.py
6
+ etc_lab_extension/formatters.py
7
+ etc_lab_extension/py.typed
8
+ etc_lab_extension/utils.py
9
+ etc_lab_extension.egg-info/PKG-INFO
10
+ etc_lab_extension.egg-info/SOURCES.txt
11
+ etc_lab_extension.egg-info/dependency_links.txt
12
+ etc_lab_extension.egg-info/top_level.txt
13
+ etc_lab_extension/supervision/__init__.py
14
+ etc_lab_extension/supervision/buffer.py
15
+ etc_lab_extension/supervision/heartbeat.py
16
+ etc_lab_extension/supervision/kiosk.py
17
+ etc_lab_extension/supervision/policy.py
18
+ etc_lab_extension/supervision/student.py
19
+ etc_lab_extension/supervision/supervisor.py
20
+ etc_lab_extension/supervision/telemetry.py
21
+ etc_lab_extension/supervision/watchdog.py
@@ -0,0 +1 @@
1
+ etc_lab_extension
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "etc-lab-extension"
7
+ version = "1.0.4"
8
+ authors = [
9
+ { name = "Dang Tuan Anh", email = "tuandanga@etc-corp.internal" },
10
+ { name = "Edutech Core JSC R&D", email = "rnd@etc-corp.internal" },
11
+ ]
12
+ description = "ETC Classroom Lab Extension Suite: Terminal UI formatters, SQLite forensic evidence extractors, and concurrency supervision daemons."
13
+ readme = { file = "README.md", content-type = "text/markdown" }
14
+ license = "MIT"
15
+ requires-python = ">=3.8"
16
+ keywords = [
17
+ "education",
18
+ "classroom",
19
+ "terminal-ui",
20
+ "forensics",
21
+ "concurrency",
22
+ "python-education",
23
+ "edtech",
24
+ "etc-corp"
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 5 - Production/Stable",
28
+ "Intended Audience :: Education",
29
+ "Intended Audience :: Developers",
30
+ "Operating System :: Microsoft :: Windows",
31
+ "Operating System :: POSIX :: Linux",
32
+ "Operating System :: MacOS",
33
+ "Programming Language :: Python :: 3",
34
+ "Programming Language :: Python :: 3.8",
35
+ "Programming Language :: Python :: 3.9",
36
+ "Programming Language :: Python :: 3.10",
37
+ "Programming Language :: Python :: 3.11",
38
+ "Programming Language :: Python :: 3.12",
39
+ "Topic :: Education",
40
+ "Topic :: Software Development :: Libraries :: Python Modules",
41
+ "Topic :: System :: Monitoring",
42
+ ]
43
+
44
+ [project.urls]
45
+ "Homepage" = "https://github.com/etc-corp/etc-lab-extension"
46
+ "Documentation" = "https://github.com/etc-corp/etc-lab-extension#readme"
47
+ "Repository" = "https://github.com/etc-corp/etc-lab-extension.git"
48
+ "Bug Tracker" = "https://github.com/etc-corp/etc-lab-extension/issues"
49
+
50
+ [tool.setuptools.packages.find]
51
+ where = ["."]
52
+ include = ["etc_lab_extension*"]
53
+
54
+ [tool.setuptools.package-data]
55
+ etc_lab_extension = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+