6 Commits
Author SHA1 Message Date
catarrh e00a96b918 Release a Windows-friendly runtime zip (v2.7.12)
Release / release (push) Waiting to run
The releases carried the wheel and the sdist; the only zip was GitHub's source
archive of the whole repository (tests, CI, tools).  A Windows user just wants
to extract a folder and double-click start.bat.

- scripts/build_release_zip.py builds simtrace-analyser-<version>.zip with a
  single top-level directory: the two Python packages, the PWA runtime files
  (frontend/tests and package.json stay out), the four launchers, the udev
  rule, the READMEs and the screenshot.  The .bat entries are written with
  CRLF line endings (cmd.exe mishandles bare-LF labels/goto), the .sh files
  keep their executable bit; LICENSE is included automatically once the repo
  has one.
- tests/test_release_zip.py pins the archive shape, the exclusions, the sw.js
  PRECACHE drift (every precached asset must travel), the CRLF/LF line endings
  and start.sh's mode.
- the release workflow builds the zip, checks it carries start.bat and the
  PWA, uploads it with the run and attaches it to the release.
- READMEs (EN/RU) and the release-notes template offer the zip as the
  Windows-friendly option; version 2.7.12, PWA cache v94.

Verified: the built zip (34 entries, 658 KB compressed) extracted and started
on Linux serves the same index.html; 553 Python + 80 Node tests.
2026-10-21 00:17:06 +03:00
catarrh b19abbd514 CI: install pyusb before the tests
tests/test_capture.py builds a DirectSniffer, whose lazy import reaches
simtrace2_pysniff.device -> usb.core; the runner has no PyUSB, so two tests
failed there while passing on a workstation that already had it.  The job now
installs the declared runtime dependency next to build.
2026-10-20 23:29:07 +03:00
catarrh 0b3c483c0b CI: a tag push builds, tests and publishes the release
The artifacts and the GitHub release were made by hand (`python -m build` plus
`gh release create`).  `.github/workflows/release.yml` now does it from the
pushed tag: Python and PWA tests, the sdist/wheel build, a check that the
wheel carries the PWA, an install-and-serve smoke test of that wheel, and
`gh release create` with the generated notes (prepended by
`.github/release-notes.md`) and the three assets (wheel, sdist, udev rule).

A `workflow_dispatch` run does everything except publish, so the pipeline can
be exercised without minting a release; the artifacts land in the run.  A tag
that does not match version.py/PWA_VERSION fails before anything is published.
2026-10-20 23:28:13 +03:00
catarrh 9e46c64490 README: pip is the install command (pipx dropped)
The release notes and the README's local-wheel examples still led with
`pipx install`; only the direct-URL form had been switched to pip earlier.
Both READMEs now show a plain `pip install <wheel>` (with the PEP 668 note to
use a virtual environment when the system Python is externally managed), and
the `gh release download` example installs with pip too.  The v2.7.10 and
v2.7.11 release bodies are edited to match.
2026-10-20 23:25:24 +03:00
catarrh efcb6c6c3f Version 2.7.11: the Windows launcher and install-doc fixes
Ships the launcher/doc commit on top of v2.7.10 as a release:
- start.bat passes --db/DB to the server (it only stored the value before) and
  sends --gsmtap-port only for gsmtap capture, like start.sh;
- both .bat launchers quote their values and keep the quoting of pass-through
  options, so paths with spaces work (--db, --web-dir, --pcap, --output);
- the READMEs describe both install paths (release artifacts or a git clone)
  and document the launchers and the Windows python-on-PATH requirement.

Version strings in version.py, pyproject.toml, PWA_VERSION and the version
test move together; SW cache simtrace-analyser-v93.
2026-10-20 23:18:57 +03:00
catarrh 65c8ab215b README: two explicit install paths; Windows launchers pass --db and quote paths
- the Install section now leads with the release artifacts (the wheel via
  pipx/pip, the direct release URL, `gh release download` for the
  version-agnostic case, and the source archive) and keeps the git clone as
  the development path.  It finally names the launchers (./start.sh,
  start.bat): a clone needs no install, but the README never said how to start
  it while the Running section only showed the console script that an install
  provides.
- Windows: the USB section now says the .bat launchers mirror the shell ones
  and call the `python` command (Python 3 must be on PATH); the Install section
  carries the same note.
- start.bat: --db/DB was parsed and then never passed to the server; it is
  passed now, and --gsmtap-port is sent only for gsmtap capture (as start.sh
  already did).  Both .bat files passed values unquoted and stripped the
  quotes of pass-through options, so paths with spaces broke
  (--db "C:\My Data\...", --web-dir, --pcap, --output); values are quoted now
  and pass-through keeps the original quoting (argument assembly through
  delayed expansion).
- the launcher usage comments include the `disabled` capture mode.
- verified the argument assembly with Wine cmd.exe and an echo harness: the
  quoted paths survive, --db arrives, --gsmtap-port appears only for gsmtap;
  547 Python + 80 Node tests.
2026-10-20 23:15:54 +03:00
14 changed files with 523 additions and 62 deletions

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
Install the wheel below — the PWA is bundled inside it:
```
pip install ./simtrace_analyser-*.whl
simtrace-analyser-server --capture gsmtap
```
The UI is then served at http://127.0.0.1:8081/. If your system Python is
externally managed (PEP 668 — common on Arch and Fedora), install into a
virtual environment first (`python3 -m venv .venv && . .venv/bin/activate`).
The source archive is the same tree a clone would have: unzip it and run
`./start.sh` (Linux/macOS) or `start.bat` (Windows). Direct SIMtrace2 capture
on Linux additionally needs the attached `70-simtrace2-pysniff.rules` udev rule.
**Runtime zip (Windows-friendly, no installer)** — `simtrace-analyser-*.zip`
is the runtime tree only (packages, PWA, launchers, docs — no tests, no git):
extract it anywhere and run `start.bat` (Windows) or `./start.sh`
(Linux/macOS). Python 3 has to be on `PATH`; `pip install pyusb` is only
needed for direct SIMtrace2 capture.
+115
View File
@@ -0,0 +1,115 @@
name: Release
# A pushed v* tag publishes a GitHub release with the wheel, the sdist and the
# udev rule. A manual run (workflow_dispatch) does everything except publish,
# so the pipeline can be exercised without minting a release.
on:
push:
tags: ['v*']
workflow_dispatch:
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: The tag matches the version strings
if: startsWith(github.ref, 'refs/tags/')
run: |
version=$(python -c "from simtrace_analyser.version import __version__; print(__version__)")
if [ "$GITHUB_REF_NAME" != "v$version" ]; then
echo "tag $GITHUB_REF_NAME does not match version.py ($version)" >&2
exit 1
fi
grep -q "PWA_VERSION = '$version'" frontend/index.html
- name: Install build tooling and the runtime dependency
run: python -m pip install --upgrade pip pyusb build
- name: Python tests
run: python -m unittest discover -s tests
- name: PWA tests
working-directory: frontend
run: node --test
- name: Build the sdist and the wheel
run: python -m build --sdist --wheel
- name: Build the runtime zip
run: python scripts/build_release_zip.py --output dist
- name: The runtime zip is complete
run: |
python - <<'PY'
import glob
import zipfile
archive = glob.glob('dist/*.zip')[0]
names = zipfile.ZipFile(archive).namelist()
for required in ('start.bat', 'frontend/index.html'):
assert any(n.endswith('/' + required) for n in names), \
'%s is missing from %s' % (required, archive)
print('%s: %d entries, launchers and PWA bundled' % (archive, len(names)))
PY
- name: The wheel bundles the PWA
run: |
python - <<'PY'
import glob
import zipfile
wheel = glob.glob('dist/*.whl')[0]
names = zipfile.ZipFile(wheel).namelist()
for required in ('simtrace_analyser/web/index.html',
'simtrace_analyser/web/sw.js'):
assert required in names, '%s is missing from %s' % (required, wheel)
print('%s: %d entries, PWA bundled' % (wheel, len(names)))
PY
- name: The installed wheel serves the PWA
run: |
python -m venv /tmp/smoke
/tmp/smoke/bin/pip install --no-deps dist/*.whl
cd /tmp
/tmp/smoke/bin/simtrace-analyser-server --capture disabled \
--db /tmp/smoke.db --port 8099 &
server=$!
for _ in $(seq 1 20); do
if curl -fsS http://127.0.0.1:8099/ -o /tmp/served-index.html; then
break
fi
sleep 0.5
done
kill "$server"
cmp /tmp/served-index.html "$GITHUB_WORKSPACE/frontend/index.html"
/tmp/smoke/bin/python -c \
"import simtrace_analyser.__main__ as m; p = m._default_web_dir(); assert p.endswith('/simtrace_analyser/web'), p"
- name: Keep the artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/*
- name: Publish the release
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--generate-notes \
--notes-file .github/release-notes.md \
dist/*.whl dist/*.tar.gz dist/*.zip 70-simtrace2-pysniff.rules
+64 -23
View File
@@ -94,41 +94,76 @@ No other dependencies. PCAP, GSMTAP, and hex dump output use only Python stdlib.
## Install
```sh
git clone https://github.com/anttro/simtrace-analyser.git
cd simtrace-analyser
pip install pyusb
```
There are two ways to get the analyser: install a release artifact (no git
history), or clone the repository for development. Both bundle the same PWA.
Or install the package into your environment:
### From a release (no git history)
Everything is on the
[latest release](https://github.com/anttro/simtrace-analyser/releases/latest).
**Wheel** (the PWA is inside the package):
```sh
pip install -e .
# then run: simtrace-analyser-server [opts]
# or: simtrace2-pysniff [opts]
```
### From a release (no git checkout)
The release artifacts bundle the PWA, so an installed server serves the same UI
as a clone. Download the wheel from the
[latest release](https://github.com/anttro/simtrace-analyser/releases/latest)
and install it:
```sh
pipx install ./simtrace_analyser-2.7.10-py3-none-any.whl
# or: pip install ./simtrace_analyser-2.7.10-py3-none-any.whl
pip install ./simtrace_analyser-2.7.12-py3-none-any.whl
# then run (the UI is served at http://127.0.0.1:8081/):
simtrace-analyser-server --capture gsmtap
```
`pip` can also fetch the wheel straight from the release page:
If your system Python is externally managed (PEP 668 — common on Arch and
Fedora), install into a virtual environment first:
`python3 -m venv .venv && . .venv/bin/activate`.
`pip` can also fetch the wheel straight from the release page (use the version
shown there):
```sh
pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.10/simtrace_analyser-2.7.10-py3-none-any.whl
pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.12/simtrace_analyser-2.7.12-py3-none-any.whl
```
With the GitHub CLI, download the latest wheel without knowing the version:
```sh
gh release download --pattern '*.whl'
pip install ./simtrace_analyser-*.whl
```
**Source archive** — the *Source code (zip / tar.gz)* assets are the full tree
without the git history: unzip, `cd` into it and use the launchers below
(`./start.sh` on Linux/macOS, `start.bat` on Windows).
**Zip (Windows-friendly, no installer)** — `simtrace-analyser-2.7.12.zip` is
the runtime tree only (packages, PWA, launchers, docs; no tests, no git):
download it, extract it anywhere and run `start.bat` (Windows) or
`./start.sh` (Linux/macOS). Python 3 has to be on `PATH`; `pip install pyusb`
is only needed for direct SIMtrace2 capture.
### From a git clone (development)
```sh
git clone https://github.com/anttro/simtrace-analyser.git
cd simtrace-analyser
./start.sh # Linux/macOS; on Windows: start.bat
```
The launchers add the checkout to `PYTHONPATH` and run
`python -m simtrace_analyser`, so no install step is needed for browsing and
GSMTAP capture; they accept the server's options (`./start.sh --capture direct
--port 8080`). Direct hardware capture needs **PyUSB** (`pip install pyusb`).
To get the console scripts (`simtrace-analyser-server`, `simtrace2-pysniff`)
install the package instead:
```sh
pip install -e .
simtrace-analyser-server --capture gsmtap
```
On Windows the `.bat` launchers run the `python` command, so Python 3 has to be
on `PATH` (check with `python --version`); direct USB capture additionally
needs the driver swap described in [USB Device Access](#usb-device-access).
## Running
### Analysis server + PWA (`simtrace-analyser-server`)
@@ -397,6 +432,12 @@ Windows does not ship a libusb-compatible driver for SIMtrace2. Use
After that, `python -m simtrace2_pysniff` works identically to Linux.
The Windows launchers match their shell counterparts and pass every option
through: `start.bat --capture direct` starts the analyser server and
`sniff-start.bat` the capture utility. Both call the `python` command, so
Python 3 must be on `PATH` (verify with `python --version` in a new command
prompt).
## Utility CLI Options
```
+67 -23
View File
@@ -99,41 +99,79 @@ SIM/UICC из UDP-потока GSMTAP (или импортирует файлы
## Установка
```sh
git clone https://github.com/anttro/simtrace-analyser.git
cd simtrace-analyser
pip install pyusb
```
Есть два способа получить анализатор: установить артефакт релиза (без истории
git) или склонировать репозиторий для разработки. В обоих случаях в комплекте
одна и та же PWA.
Или установите пакет в своё окружение:
### Из релиза (без истории git)
Всё находится на странице
[последнего релиза](https://github.com/anttro/simtrace-analyser/releases/latest).
**Wheel** (PWA внутри пакета):
```sh
pip install -e .
# затем запуск: simtrace-analyser-server [opts]
# или: simtrace2-pysniff [opts]
```
### Из релиза (без клонирования репозитория)
Релизные артефакты содержат PWA внутри пакета, поэтому установленный сервер
отдаёт тот же интерфейс, что и при запуске из клона. Скачайте wheel со
страницы [последнего релиза](https://github.com/anttro/simtrace-analyser/releases/latest)
и установите его:
```sh
pipx install ./simtrace_analyser-2.7.10-py3-none-any.whl
# или: pip install ./simtrace_analyser-2.7.10-py3-none-any.whl
pip install ./simtrace_analyser-2.7.12-py3-none-any.whl
# затем запуск (интерфейс отдаётся на http://127.0.0.1:8081/):
simtrace-analyser-server --capture gsmtap
```
`pip` также может скачать wheel прямо со страницы релиза:
Если системный Python управляется извне (PEP 668 — обычное дело в Arch и
Fedora), сначала создайте виртуальное окружение:
`python3 -m venv .venv && . .venv/bin/activate`.
`pip` также может скачать wheel прямо со страницы релиза (подставьте версию,
указанную там):
```sh
pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.10/simtrace_analyser-2.7.10-py3-none-any.whl
pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.12/simtrace_analyser-2.7.12-py3-none-any.whl
```
С GitHub CLI можно скачать wheel последнего релиза, не зная версии:
```sh
gh release download --pattern '*.whl'
pip install ./simtrace_analyser-*.whl
```
**Архив исходников** — ассеты *Source code (zip / tar.gz)* содержат полное
дерево без истории git: распакуйте, перейдите в каталог и используйте скрипты
запуска ниже (`./start.sh` в Linux/macOS, `start.bat` в Windows).
**Zip (для Windows, без установки)** — `simtrace-analyser-2.7.12.zip`
содержит только рабочее дерево (пакеты, PWA, скрипты запуска, документацию;
без тестов и git): скачайте, распакуйте в любое место и запустите `start.bat`
(Windows) или `./start.sh` (Linux/macOS). Python 3 должен быть в `PATH`;
`pip install pyusb` нужен только для прямого захвата с SIMtrace2.
### Из клона репозитория (для разработки)
```sh
git clone https://github.com/anttro/simtrace-analyser.git
cd simtrace-analyser
./start.sh # Linux/macOS; в Windows: start.bat
```
Скрипты запуска добавляют каталог в `PYTHONPATH` и запускают
`python -m simtrace_analyser`, поэтому для просмотра и захвата GSMTAP
установка не нужна; они принимают параметры сервера
(`./start.sh --capture direct --port 8080`). Для прямого захвата с
оборудования нужен **PyUSB** (`pip install pyusb`).
Чтобы получить консольные команды (`simtrace-analyser-server`,
`simtrace2-pysniff`), установите пакет:
```sh
pip install -e .
simtrace-analyser-server --capture gsmtap
```
В Windows скрипты `.bat` вызывают команду `python`, поэтому Python 3 должен
быть в `PATH` (проверьте `python --version`); для прямого захвата по USB
дополнительно нужна замена драйвера, описанная в разделе
[Доступ к USB-устройству](#доступ-к-usb-устройству).
## Запуск
### Анализирующий сервер + PWA (`simtrace-analyser-server`)
@@ -407,6 +445,12 @@ sudo udevadm trigger
После этого `python -m simtrace2_pysniff` работает так же, как в Linux.
Скрипты запуска для Windows соответствуют shell-версиям и передают все
параметры: `start.bat --capture direct` запускает сервер анализатора, а
`sniff-start.bat` — утилиту захвата. Оба вызывают команду `python`, поэтому
Python 3 должен быть в `PATH` (проверьте `python --version` в новом окне
команды).
## Параметры CLI утилиты
```
+1 -1
View File
@@ -3389,7 +3389,7 @@ function onSearchChange() {
}
// ──────────────────── Versioning ────────────────────
const PWA_VERSION = '2.7.10';
const PWA_VERSION = '2.7.12';
const MIN_SERVER_VERSION = '2.3.0';
function parseVersion(v) {
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'simtrace-analyser-v92';
const CACHE = 'simtrace-analyser-v94';
const PRECACHE = [
'index.html',
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "simtrace-analyser"
version = "2.7.10"
version = "2.7.12"
description = "SIMtrace Analyser — APDU trace analyser for GSMTAP/PCAP captures (bundles the simtrace2-pysniff utility)"
readme = {file = "README.md", content-type = "text/markdown"}
license = {text = "GPL-2.0-or-later"}
+132
View File
@@ -0,0 +1,132 @@
"""Build the ready-to-run runtime zip for a GitHub release.
The wheel needs ``pip`` and the GitHub source archive carries the whole
repository (tests, CI, the gitignored ``tools/``). This zip is the runtime
tree only: extract it anywhere, run ``start.bat`` on Windows or
``./start.sh`` elsewhere, and the server serves the bundled PWA. Python 3
must be on ``PATH``; PyUSB is only needed for direct hardware capture.
The build is deliberately simple - the explicit include lists below are the
whole manifest, so nothing from ``tests/``, ``.github/``, ``pyproject.toml``
or a build directory can leak into the archive by accident.
"""
import argparse
import sys
import zipfile
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
# The script lives outside the packages; import the version from the checkout.
sys.path.insert(0, str(REPO))
from simtrace_analyser.version import __version__ # noqa: E402
# The Python packages (all modules, no caches).
PACKAGES = ('simtrace_analyser', 'simtrace2_pysniff')
# The PWA runtime files; ``tests/`` and ``package.json`` are dev-only.
FRONTEND = 'frontend'
FRONTEND_EXCLUDE = ('tests', 'package.json')
# Repo-root files that make the extracted tree usable. LICENSE is included
# once the repository has one.
ROOT_FILES = (
'start.sh',
'start.bat',
'sniff-start.sh',
'sniff-start.bat',
'70-simtrace2-pysniff.rules',
'README.md',
'README_RUS.md',
'frontend.png',
'LICENSE',
)
# Skip editor/byte-code droppings wherever they appear.
SKIP_DIRS = ('__pycache__',)
SKIP_NAMES = ('.DS_Store',)
SKIP_SUFFIXES = ('.pyc',)
def _files(root):
"""Yield the regular files under *root*, sorted and cache-free."""
for path in sorted(root.rglob('*')):
if not path.is_file():
continue
if any(part in SKIP_DIRS for part in path.parts):
continue
if path.name in SKIP_NAMES or path.suffix in SKIP_SUFFIXES:
continue
yield path
def _write_bat(zf, path, arcname):
"""Write a .bat entry with CRLF line endings.
The checkout stores the batch files with LF, and cmd.exe mishandles a
batch file whose lines end in a bare LF (labels and ``goto`` in
particular), so the archive gets the Windows form. The source files
stay untouched. ``writestr`` does not copy the file mode, so set it.
"""
data = path.read_bytes().replace(b'\r\n', b'\n').replace(b'\n', b'\r\n')
info = zipfile.ZipInfo.from_file(path, arcname)
info.external_attr = 0o644 << 16
info.compress_type = zipfile.ZIP_DEFLATED
zf.writestr(info, data)
def build_zip(output_dir, version=None):
"""Write ``simtrace-analyser-<version>.zip`` into *output_dir*.
Returns the archive path. The zip has a single top-level directory
``simtrace-analyser-<version>/`` holding the runtime tree.
"""
version = version or __version__
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
archive = output_dir / ('simtrace-analyser-%s.zip' % version)
top = 'simtrace-analyser-%s' % version
with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as zf:
for package in PACKAGES:
for path in _files(REPO / package):
zf.write(path, '%s/%s' % (top, path.relative_to(REPO).as_posix()))
for path in _files(REPO / FRONTEND):
rel = path.relative_to(REPO / FRONTEND)
if rel.parts[0] in FRONTEND_EXCLUDE:
continue
zf.write(path, '%s/%s' % (top, path.relative_to(REPO).as_posix()))
for name in ROOT_FILES:
path = REPO / name
if not path.is_file():
# LICENSE is not in the repository yet; include it once it is.
continue
arcname = '%s/%s' % (top, name)
if path.suffix == '.bat':
_write_bat(zf, path, arcname)
else:
zf.write(path, arcname)
return archive
def main(argv=None):
parser = argparse.ArgumentParser(
description='Build the runtime zip attached to a release')
parser.add_argument('--output', default='dist', metavar='DIR',
help='directory for the archive (default: dist)')
args = parser.parse_args(argv)
archive = build_zip(args.output)
with zipfile.ZipFile(archive) as zf:
entries = len(zf.namelist())
print(archive)
print('%d entries' % entries)
return 0
if __name__ == '__main__':
sys.exit(main())
+1 -1
View File
@@ -1,3 +1,3 @@
"""Single source of truth for the SIMtrace Analyser version."""
__version__ = '2.7.10'
__version__ = '2.7.12'
+7 -7
View File
@@ -59,7 +59,7 @@ if "%~1"=="--inactivity-timeout" (
shift
goto :parse_args
)
set "EXTRA_ARGS=!EXTRA_ARGS! %~1"
set "EXTRA_ARGS=!EXTRA_ARGS! %1"
shift
goto :parse_args
@@ -67,11 +67,11 @@ goto :parse_args
echo Starting simtrace2-pysniff...
set "ARGS="
if not "%GSMTAP%"=="" set "ARGS=!ARGS! --gsmtap %GSMTAP%"
if not "%PCAP%"=="" set "ARGS=!ARGS! --pcap %PCAP%"
if not "%OUTPUT%"=="" set "ARGS=!ARGS! --output %OUTPUT%"
if not "%FORMAT%"=="" set "ARGS=!ARGS! --format %FORMAT%"
if not "%INACTIVITY_TIMEOUT%"=="0" set "ARGS=!ARGS! --inactivity-timeout %INACTIVITY_TIMEOUT%"
if not "%GSMTAP%"=="" set "ARGS=!ARGS! --gsmtap "%GSMTAP%""
if not "%PCAP%"=="" set "ARGS=!ARGS! --pcap "%PCAP%""
if not "%OUTPUT%"=="" set "ARGS=!ARGS! --output "%OUTPUT%""
if not "%FORMAT%"=="" set "ARGS=!ARGS! --format "%FORMAT%""
if not "%INACTIVITY_TIMEOUT%"=="0" set "ARGS=!ARGS! --inactivity-timeout "%INACTIVITY_TIMEOUT%""
set "PYTHONPATH=%~dp0"
python -m simtrace2_pysniff %ARGS% %EXTRA_ARGS%
python -m simtrace2_pysniff !ARGS! !EXTRA_ARGS!
+8 -3
View File
@@ -3,7 +3,7 @@ setlocal enabledelayedexpansion
:: simtrace-analyser-server startup script for Windows
::
:: Usage: start.bat [--capture gsmtap|direct] [--port PORT] [--db PATH] [--gsmtap-port PORT]
:: Usage: start.bat [--capture gsmtap|direct|disabled] [--port PORT] [--db PATH] [--gsmtap-port PORT]
::
:: Options set via environment variables act as defaults; CLI flags override them.
@@ -42,7 +42,7 @@ if "%~1"=="--gsmtap-port" (
shift
goto :parse_args
)
set "EXTRA_ARGS=!EXTRA_ARGS! %~1"
set "EXTRA_ARGS=!EXTRA_ARGS! %1"
shift
goto :parse_args
@@ -50,5 +50,10 @@ goto :parse_args
echo Starting simtrace-analyser-server...
echo PWA (simtrace-analyser) will be served at http://127.0.0.1:%PORT%/
set "ARGS=--capture "%CAPTURE%" --port "%PORT%""
if not "%DB%"=="" set "ARGS=!ARGS! --db "%DB%""
if /i "%CAPTURE%"=="gsmtap" set "ARGS=!ARGS! --gsmtap-port "%GSMTAP_PORT%""
set "ARGS=!ARGS! !EXTRA_ARGS!"
set "PYTHONPATH=%~dp0"
python -m simtrace_analyser --capture %CAPTURE% --port %PORT% --gsmtap-port %GSMTAP_PORT% %EXTRA_ARGS%
python -m simtrace_analyser !ARGS!
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash
# simtrace-analyser-server startup script
#
# Usage: ./start.sh [--capture gsmtap|direct] [--port PORT] [--db PATH] [--gsmtap-port PORT]
# Usage: ./start.sh [--capture gsmtap|direct|disabled] [--port PORT] [--db PATH] [--gsmtap-port PORT]
#
# Options set via environment variables act as defaults; CLI flags override them.
+1 -1
View File
@@ -224,7 +224,7 @@ class TestImportEndpoint(unittest.TestCase):
class TestVersion(unittest.TestCase):
def test_package_version(self):
from simtrace2_pysniff import __version__
self.assertEqual(__version__, '2.7.10')
self.assertEqual(__version__, '2.7.12')
def test_status_includes_version(self):
import os
+104
View File
@@ -0,0 +1,104 @@
"""Tests for the ready-to-run release zip (scripts/build_release_zip.py)."""
import importlib.util
import re
import tempfile
import unittest
import zipfile
from pathlib import Path
from simtrace_analyser.version import __version__
REPO = Path(__file__).resolve().parents[1]
# scripts/ is not a package, so load the builder from its path.
_spec = importlib.util.spec_from_file_location(
'build_release_zip', REPO / 'scripts' / 'build_release_zip.py')
build_release_zip = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(build_release_zip)
class TestReleaseZip(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._tmp = tempfile.TemporaryDirectory()
cls.archive = build_release_zip.build_zip(cls._tmp.name)
with zipfile.ZipFile(cls.archive) as zf:
cls.names = zf.namelist()
@classmethod
def tearDownClass(cls):
cls._tmp.cleanup()
def test_name_and_single_top_level_directory(self):
top = 'simtrace-analyser-%s' % __version__
self.assertEqual(self.archive.name, top + '.zip')
for name in self.names:
self.assertTrue(name.startswith(top + '/'),
'%s is outside %s/' % (name, top))
def test_required_entries(self):
top = 'simtrace-analyser-%s' % __version__
for rel in (
'simtrace_analyser/__main__.py',
'simtrace_analyser/version.py',
'simtrace2_pysniff/__main__.py',
'frontend/index.html',
'frontend/sw.js',
'frontend/manifest.json',
'start.sh',
'start.bat',
'sniff-start.sh',
'sniff-start.bat',
'70-simtrace2-pysniff.rules',
'README.md'):
self.assertIn('%s/%s' % (top, rel), self.names)
def test_dev_only_entries_are_excluded(self):
for name in self.names:
self.assertNotIn('/tests/', name)
self.assertNotIn('/__pycache__/', name)
self.assertNotIn('.pyc', name)
self.assertNotIn('/.git', name)
self.assertNotIn('/.github/', name)
self.assertNotIn(
'simtrace-analyser-%s/frontend/package.json' % __version__,
self.names)
self.assertNotIn(
'simtrace-analyser-%s/pyproject.toml' % __version__, self.names)
def test_precache_files_are_in_the_zip(self):
# Drift guard: every asset the service worker precaches must travel
# with the PWA, otherwise an offline install fails on a fresh extract.
text = (REPO / 'frontend' / 'sw.js').read_text()
match = re.search(r'PRECACHE\s*=\s*\[(.*?)\]', text, re.S)
self.assertIsNotNone(match, 'no PRECACHE array in frontend/sw.js')
assets = re.findall(r"'([^']+)'", match.group(1))
self.assertTrue(assets)
top = 'simtrace-analyser-%s' % __version__
for asset in assets:
self.assertIn('%s/frontend/%s' % (top, asset), self.names,
'precached %s is missing from the zip' % asset)
def test_batch_files_use_crlf(self):
with zipfile.ZipFile(self.archive) as zf:
bats = [n for n in self.names if n.endswith('.bat')]
self.assertTrue(bats)
for name in bats:
data = zf.read(name)
self.assertIn(b'\r\n', data, name)
self.assertNotIn(b'\n', data.replace(b'\r\n', b''),
'%s has a bare LF' % name)
def test_shell_script_is_lf_and_executable(self):
name = 'simtrace-analyser-%s/start.sh' % __version__
with zipfile.ZipFile(self.archive) as zf:
info = zf.getinfo(name)
data = zf.read(name)
self.assertNotIn(b'\r\n', data)
self.assertTrue(info.external_attr >> 16 & 0o100,
'start.sh lost its executable bit')
if __name__ == '__main__':
unittest.main()