16 Commits
Author SHA1 Message Date
me0nline 355c6e1bc0 Update README.md documentation and commands to reflect compilation/ and tests/ paths
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 1m34s
2026-09-04 15:58:03 +02:00
me0nline 907616511b Update release-windows.yml workflow to use compilation/ directory 2026-09-04 15:57:14 +02:00
me0nline 939fa4270a Update release-linux.yml workflow to use compilation/ directory 2026-09-04 15:57:02 +02:00
me0nline 1f4bf3219b Update CI workflow with compilation/ and tests/ paths 2026-09-04 15:56:50 +02:00
me0nline df03c52a05 Update tests/test_pipeline.py to resolve paths relative to repository root and src/ directory 2026-09-04 15:56:37 +02:00
me0nline d63a623763 Update compilation/upload_release.py to resolve paths relative to repo root 2026-09-04 15:56:24 +02:00
me0nline 7ed264db5a Update compilation/package_dist.py to resolve paths relative to repo root 2026-09-04 15:56:01 +02:00
me0nline 6fec838344 Move test_pipeline.py from repository root to tests/ directory 2026-09-04 15:55:51 +02:00
me0nline 4c160924f7 Move build and release tools (package_dist.py, upload_release.py, requirements.txt) into compilation/ directory 2026-09-04 15:55:44 +02:00
me0nline 99be50ebc6 Update Server.py reference to src/Server.py in forwarder deployment READMEs
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 1m32s
2026-09-04 15:51:37 +02:00
me0nline 85f0d94805 Update README.md documentation and repo structure to reflect src/ directory 2026-09-04 15:51:23 +02:00
me0nline 1a18c4c079 Update CI workflow to execute server and client scripts from src/ directory 2026-09-04 15:50:34 +02:00
me0nline a770e24f26 Update test_pipeline.py to import client forwarders from src/ directory 2026-09-04 15:50:26 +02:00
me0nline f7ebc6c0a1 Update unit test suites to import components from src/ directory 2026-09-04 15:50:14 +02:00
me0nline 86649f796d Update package_dist.py to resolve source files from src/ directory 2026-09-04 15:49:52 +02:00
me0nline 78fc2ac8c5 Move source files Server.py, Win_Client.py, and Linux_Client.py into src/ directory 2026-09-04 15:49:32 +02:00
17 changed files with 75 additions and 57 deletions
+5 -5
View File
@@ -24,11 +24,11 @@ jobs:
apt-get install -y python3 python3-pip python3-venv curl apt-get install -y python3 python3-pip python3-venv curl
fi fi
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
pip3 install -r requirements.txt --break-system-packages || pip3 install -r requirements.txt pip3 install -r compilation/requirements.txt --break-system-packages || pip3 install -r compilation/requirements.txt
- name: Verify Python Syntax - name: Verify Python Syntax
run: | run: |
python3 -m py_compile Server.py Win_Client.py Linux_Client.py package_dist.py upload_release.py test_pipeline.py tests/*.py python3 -m py_compile src/Server.py src/Win_Client.py src/Linux_Client.py compilation/package_dist.py compilation/upload_release.py tests/test_pipeline.py tests/*.py
- name: Run Component Unit Tests - name: Run Component Unit Tests
run: | run: |
@@ -40,10 +40,10 @@ jobs:
rm -f server_config.json client_config.json logar_state.db client_state.json rm -f server_config.json client_config.json logar_state.db client_state.json
# 1. Initialize server config and export client configuration # 1. Initialize server config and export client configuration
python3 Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json python3 src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
# 2. Launch LOGAR server in the background # 2. Launch LOGAR server in the background
python3 Server.py & python3 src/Server.py &
SERVER_PID=$! SERVER_PID=$!
echo "[*] Server launched in background with PID $SERVER_PID" echo "[*] Server launched in background with PID $SERVER_PID"
@@ -65,7 +65,7 @@ jobs:
fi fi
# 4. Execute end-to-end integration test # 4. Execute end-to-end integration test
python3 test_pipeline.py python3 tests/test_pipeline.py
# 5. Cleanly terminate background server # 5. Cleanly terminate background server
kill $SERVER_PID || true kill $SERVER_PID || true
+3 -3
View File
@@ -26,11 +26,11 @@ jobs:
apt-get install -y python3 python3-pip python3-venv binutils zip apt-get install -y python3 python3-pip python3-venv binutils zip
fi fi
python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true python3 -m pip install --upgrade pip --break-system-packages || python3 -m pip install --upgrade pip || true
pip3 install pyinstaller -r requirements.txt --break-system-packages || pip3 install pyinstaller -r requirements.txt pip3 install pyinstaller -r compilation/requirements.txt --break-system-packages || pip3 install pyinstaller -r compilation/requirements.txt
- name: Compile Standalone Linux Binaries - name: Compile Standalone Linux Binaries
run: | run: |
python3 package_dist.py --target linux python3 compilation/package_dist.py --target linux
- name: Publish Linux Release Assets - name: Publish Linux Release Assets
env: env:
@@ -39,4 +39,4 @@ jobs:
GITEA_REPOSITORY: ${{ github.repository }} GITEA_REPOSITORY: ${{ github.repository }}
GITEA_REF_NAME: ${{ inputs.tag || github.ref_name }} GITEA_REF_NAME: ${{ inputs.tag || github.ref_name }}
run: | run: |
python3 upload_release.py --skip-build python3 compilation/upload_release.py --skip-build
+3 -3
View File
@@ -35,7 +35,7 @@ jobs:
} }
} }
& $py -m pip install --upgrade pip & $py -m pip install --upgrade pip
& $py -m pip install pyinstaller -r requirements.txt & $py -m pip install pyinstaller -r compilation/requirements.txt
- name: Compile Standalone Windows Binaries - name: Compile Standalone Windows Binaries
shell: powershell shell: powershell
@@ -46,7 +46,7 @@ jobs:
$py = "py -3.12" $py = "py -3.12"
} }
} }
& $py package_dist.py --target windows & $py compilation/package_dist.py --target windows
- name: Publish Windows Release Assets - name: Publish Windows Release Assets
shell: powershell shell: powershell
@@ -62,4 +62,4 @@ jobs:
$py = "py -3.12" $py = "py -3.12"
} }
} }
& $py upload_release.py --skip-build & $py compilation/upload_release.py --skip-build
+29 -25
View File
@@ -88,7 +88,7 @@ graph TB
- A cryptographically random authentication secret token (`auth_token`). - A cryptographically random authentication secret token (`auth_token`).
- **Client Configuration Exporter**: - **Client Configuration Exporter**:
```bash ```bash
python Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json python src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
``` ```
Produces an anonymous client config containing only the server socket coordinates, authentication token, and the encryption-only public key & fingerprint. Produces an anonymous client config containing only the server socket coordinates, authentication token, and the encryption-only public key & fingerprint.
- **Socket Protocol Framing**: - **Socket Protocol Framing**:
@@ -177,20 +177,24 @@ LOGAR/
│ ├── ci.yml # Continuous Integration automated test suite (runs on every push) │ ├── ci.yml # Continuous Integration automated test suite (runs on every push)
│ ├── release-linux.yml # Linux release workflow (compiles Server.bin, Linux_Client.bin, checksums) │ ├── release-linux.yml # Linux release workflow (compiles Server.bin, Linux_Client.bin, checksums)
│ └── release-windows.yml # Windows release workflow (compiles Server.exe, Win_Client.exe, checksums) │ └── release-windows.yml # Windows release workflow (compiles Server.exe, Win_Client.exe, checksums)
├── .gitignore # Ignore venv, caches, DBs, and private keys ├── compilation/ # Build, packaging, and release automation tools
├── requirements.txt # Unified dependencies │ ├── package_dist.py # Multi-platform standalone binary packaging script
├── README.md # Comprehensive documentation │ ├── requirements.txt # Unified project dependencies
├── Server.py # Central TCP server and Hermes API │ └── upload_release.py # Direct Gitea REST API release asset publisher
├── Win_Client.py # Windows edge forwarder ├── src/ # Core application source modules
├── Linux_Client.py # Linux edge forwarder │ ├── __init__.py
├── server_config.sample.json # Central server sample configuration ├── Server.py # Central TCP server and Hermes API
├── package_dist.py # Multi-platform standalone binary packaging script │ ├── Win_Client.py # Windows edge forwarder
├── upload_release.py # Direct Gitea REST API release asset publisher │ └── Linux_Client.py # Linux edge forwarder
├── test_pipeline.py # End-to-end integration test ├── tests/ # Automated test suites
├── tests/ # Unified unit test suites ├── test_linux_client.py # Linux client unit tests
│ ├── test_pipeline.py # End-to-end integration test
│ ├── test_server.py # Server unit tests │ ├── test_server.py # Server unit tests
── test_win_client.py # Windows client unit tests ── test_win_client.py # Windows client unit tests
│ └── test_linux_client.py # Linux client unit tests ├── .gitignore # Ignore venv, caches, DBs, and private keys
├── README.md # Comprehensive documentation
├── RELEASE_NOTES.md # Release history and changelog
├── server_config.sample.json # Central server sample configuration
└── out/ # Edge forwarder deployment packages └── out/ # Edge forwarder deployment packages
├── win_client/ ├── win_client/
│ ├── client_config.sample.json # Reference client configuration │ ├── client_config.sample.json # Reference client configuration
@@ -208,15 +212,15 @@ LOGAR/
1. **Install dependencies**: 1. **Install dependencies**:
```bash ```bash
pip install -r requirements.txt pip install -r compilation/requirements.txt
``` ```
2. **Start the server** (generates `server_config.json` and keypair on first run): 2. **Start the server** (generates `server_config.json` and keypair on first run):
```bash ```bash
python Server.py python src/Server.py
``` ```
3. **Export a client configuration**: 3. **Export a client configuration**:
```bash ```bash
python Server.py --create-client-config --server-host <SERVER_IP> --server-port 9443 --client-out client_config.json python src/Server.py --create-client-config --server-host <SERVER_IP> --server-port 9443 --client-out client_config.json
``` ```
### 2. Windows Client Deployment ### 2. Windows Client Deployment
@@ -287,23 +291,23 @@ The pipeline test exercises invalid token rejection, encrypted socket streaming,
1. **Start the server** in Shell 1 (creates `server_config.json` on first run): 1. **Start the server** in Shell 1 (creates `server_config.json` on first run):
```bash ```bash
python Server.py python src/Server.py
``` ```
2. **Export client configuration** in Shell 2 (required for testing): 2. **Export client configuration** in Shell 2 (required for testing):
```bash ```bash
python Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json python src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
``` ```
3. **Execute the integration test** in Shell 2: 3. **Execute the integration test** in Shell 2:
```bash ```bash
python test_pipeline.py python tests/test_pipeline.py
``` ```
## Continuous Integration via Gitea Actions ## Continuous Integration via Gitea Actions
Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request: Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request:
1. **Syntax Compilation**: Validates all Python scripts (`Server.py`, `Win_Client.py`, `Linux_Client.py`, `package_dist.py`, `upload_release.py`, `test_pipeline.py`, and test suites). 1. **Syntax Compilation**: Validates all Python scripts (`src/Server.py`, `src/Win_Client.py`, `src/Linux_Client.py`, `compilation/package_dist.py`, `compilation/upload_release.py`, `tests/test_pipeline.py`, and test suites).
2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`). 2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`).
3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance. 3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `tests/test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance.
--- ---
@@ -360,13 +364,13 @@ git push origin v1.0.1
You can also compile and package binaries locally anytime: You can also compile and package binaries locally anytime:
```bash ```bash
# Windows # Windows
py -3.12 package_dist.py --target windows py -3.12 compilation/package_dist.py --target windows
# Linux # Linux
python3 package_dist.py --target linux python3 compilation/package_dist.py --target linux
``` ```
To upload local builds directly to Gitea: To upload local builds directly to Gitea:
```powershell ```powershell
python upload_release.py --tag v1.0.1 --token <YOUR_GITEA_TOKEN> python compilation/upload_release.py --tag v1.0.1 --token <YOUR_GITEA_TOKEN>
``` ```
*(Environment variables `GITEA_TOKEN`, `GITEA_SERVER_URL`, `GITEA_REPOSITORY`, and `GITEA_REF_NAME` are also supported automatically).* *(Environment variables `GITEA_TOKEN`, `GITEA_SERVER_URL`, `GITEA_REPOSITORY`, and `GITEA_REF_NAME` are also supported automatically).*
@@ -7,9 +7,10 @@ import platform
import subprocess import subprocess
import argparse import argparse
ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
DIST_DIR = os.path.abspath("dist") SRC_DIR = os.path.join(ROOT_DIR, "src")
BUILD_TEMP = os.path.abspath("build_temp") DIST_DIR = os.path.join(ROOT_DIR, "dist")
BUILD_TEMP = os.path.join(ROOT_DIR, "build_temp")
def clean_and_prep(): def clean_and_prep():
if os.path.exists(DIST_DIR): if os.path.exists(DIST_DIR):
@@ -55,7 +56,7 @@ def build_linux_zipapp_fallback():
# Linux Client zipapp # Linux Client zipapp
app_dir = os.path.join(BUILD_TEMP, "linux_app") app_dir = os.path.join(BUILD_TEMP, "linux_app")
os.makedirs(app_dir, exist_ok=True) os.makedirs(app_dir, exist_ok=True)
shutil.copy(os.path.join(ROOT_DIR, "Linux_Client.py"), os.path.join(app_dir, "Linux_Client.py")) shutil.copy(os.path.join(SRC_DIR, "Linux_Client.py"), os.path.join(app_dir, "Linux_Client.py"))
client_out = os.path.join(DIST_DIR, "Linux_Client.bin") client_out = os.path.join(DIST_DIR, "Linux_Client.bin")
zipapp.create_archive( zipapp.create_archive(
source=app_dir, source=app_dir,
@@ -66,7 +67,7 @@ def build_linux_zipapp_fallback():
# Server zipapp # Server zipapp
srv_dir = os.path.join(BUILD_TEMP, "linux_srv") srv_dir = os.path.join(BUILD_TEMP, "linux_srv")
os.makedirs(srv_dir, exist_ok=True) os.makedirs(srv_dir, exist_ok=True)
shutil.copy(os.path.join(ROOT_DIR, "Server.py"), os.path.join(srv_dir, "Server.py")) shutil.copy(os.path.join(SRC_DIR, "Server.py"), os.path.join(srv_dir, "Server.py"))
server_out = os.path.join(DIST_DIR, "Server.bin") server_out = os.path.join(DIST_DIR, "Server.bin")
zipapp.create_archive( zipapp.create_archive(
source=srv_dir, source=srv_dir,
@@ -77,10 +78,10 @@ def build_linux_zipapp_fallback():
def build_windows(): def build_windows():
print("[*] Compiling Windows standalone executables...") print("[*] Compiling Windows standalone executables...")
win_client_script = os.path.join(ROOT_DIR, "Win_Client.py") win_client_script = os.path.join(SRC_DIR, "Win_Client.py")
build_pyinstaller_binary(win_client_script, "Win_Client") build_pyinstaller_binary(win_client_script, "Win_Client")
server_script = os.path.join(ROOT_DIR, "Server.py") server_script = os.path.join(SRC_DIR, "Server.py")
build_pyinstaller_binary(server_script, "Server") build_pyinstaller_binary(server_script, "Server")
client_bin = os.path.join(DIST_DIR, "Win_Client.exe") client_bin = os.path.join(DIST_DIR, "Win_Client.exe")
@@ -111,10 +112,10 @@ def build_linux():
is_linux_host = platform.system() == "Linux" is_linux_host = platform.system() == "Linux"
if is_linux_host: if is_linux_host:
linux_client_script = os.path.join(ROOT_DIR, "Linux_Client.py") linux_client_script = os.path.join(SRC_DIR, "Linux_Client.py")
build_pyinstaller_binary(linux_client_script, "Linux_Client.bin") build_pyinstaller_binary(linux_client_script, "Linux_Client.bin")
server_script = os.path.join(ROOT_DIR, "Server.py") server_script = os.path.join(SRC_DIR, "Server.py")
build_pyinstaller_binary(server_script, "Server.bin") build_pyinstaller_binary(server_script, "Server.bin")
# Normalize extensions in case PyInstaller dropped .bin # Normalize extensions in case PyInstaller dropped .bin
@@ -4,7 +4,8 @@ import json
import argparse import argparse
import urllib.request import urllib.request
import urllib.parse import urllib.parse
import mimetypes ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, os.path.dirname(__file__))
import package_dist import package_dist
import time import time
@@ -162,8 +163,8 @@ def main():
if not notes and args.notes_file and os.path.exists(args.notes_file): if not notes and args.notes_file and os.path.exists(args.notes_file):
with open(args.notes_file, "r", encoding="utf-8") as nf: with open(args.notes_file, "r", encoding="utf-8") as nf:
notes = nf.read() notes = nf.read()
elif not notes and os.path.exists("RELEASE_NOTES.md"): elif not notes and os.path.exists(os.path.join(ROOT_DIR, "RELEASE_NOTES.md")):
with open("RELEASE_NOTES.md", "r", encoding="utf-8") as nf: with open(os.path.join(ROOT_DIR, "RELEASE_NOTES.md"), "r", encoding="utf-8") as nf:
notes = nf.read() notes = nf.read()
elif not notes: elif not notes:
notes = ( notes = (
@@ -184,9 +185,9 @@ def main():
print("[*] Assembling compiled binaries...") print("[*] Assembling compiled binaries...")
package_dist.main() package_dist.main()
dist_dir = os.path.abspath("dist") dist_dir = os.path.join(ROOT_DIR, "dist")
if not os.path.exists(dist_dir) or not os.listdir(dist_dir): if not os.path.exists(dist_dir) or not os.listdir(dist_dir):
print("[!] No binaries found in dist/. Run package_dist.py first.") print(f"[!] No binaries found in {dist_dir}. Run package_dist.py first.")
sys.exit(1) sys.exit(1)
print(f"[*] Connecting to Gitea: {args.url} (repo: {args.repo})...") print(f"[*] Connecting to Gitea: {args.url} (repo: {args.repo})...")
+1 -1
View File
@@ -22,7 +22,7 @@ Standalone compiled binary distribution for Linux edge servers running systemd.
Run the following command on your central LOGAR server to export a client bundle tailored for your environment: Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
```bash ```bash
python Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json python src/Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
``` ```
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub. - Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
+1 -1
View File
@@ -22,7 +22,7 @@ Standalone compiled executable distribution for Windows Server and workstation e
Run the following command on your central LOGAR server to export a client bundle tailored for your environment: Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
```bash ```bash
python Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json python src/Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
``` ```
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub. - Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
View File
View File
View File
+1
View File
@@ -8,6 +8,7 @@ import warnings
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
import Linux_Client import Linux_Client
import pgpy import pgpy
+13 -4
View File
@@ -9,6 +9,12 @@ import urllib.request
import warnings import warnings
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
# Ensure repository root and src/ directory are in sys.path
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
SRC_DIR = os.path.join(ROOT_DIR, "src")
sys.path.insert(0, ROOT_DIR)
sys.path.insert(0, SRC_DIR)
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
import pgpy import pgpy
@@ -20,13 +26,16 @@ HERMES_PORT = 8443
def run_tests(): def run_tests():
print("=== [1] Verifying server_config.json & client_config.json ===") print("=== [1] Verifying server_config.json & client_config.json ===")
assert os.path.exists("server_config.json"), "server_config.json must exist" server_cfg_path = "server_config.json" if os.path.exists("server_config.json") else os.path.join(ROOT_DIR, "server_config.json")
assert os.path.exists("client_config.json"), "client_config.json must exist" client_cfg_path = "client_config.json" if os.path.exists("client_config.json") else os.path.join(ROOT_DIR, "client_config.json")
assert os.path.exists(server_cfg_path), f"{server_cfg_path} must exist"
assert os.path.exists(client_cfg_path), f"{client_cfg_path} must exist"
with open("client_config.json", "r", encoding="utf-8") as f: with open(client_cfg_path, "r", encoding="utf-8") as f:
client_conf = json.load(f) client_conf = json.load(f)
with open("server_config.json", "r", encoding="utf-8") as f: with open(server_cfg_path, "r", encoding="utf-8") as f:
server_conf = json.load(f) server_conf = json.load(f)
assert "server_name" not in client_conf, "client_config.json must NOT contain server_name" assert "server_name" not in client_conf, "client_config.json must NOT contain server_name"
+2 -1
View File
@@ -11,8 +11,9 @@ from datetime import datetime, timezone, timedelta
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
# Ensure parent directory is in path to import Server # Ensure parent directory and src directory are in path to import Server
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
import Server import Server
import pgpy import pgpy
+1
View File
@@ -8,6 +8,7 @@ import warnings
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
import Win_Client import Win_Client
import pgpy import pgpy