angles-python-client
A small Python client for the Angles Dashboard REST API, which allows python test frameworks to publish their automated test results.
Install (local / editable)
pip install -e .
Quick usage (singleton reporter)
Use angles_reporter when you want one simple process-wide reporter.
from angles_python_client import angles_reporter
from angles_python_client.models import Artifact, ScreenshotPlatform, Platform
angles_reporter.set_base_url("http://127.0.0.1:3000/rest/api/v1.0/")
build = angles_reporter.start_build(
name="TestRunName",
team="Team",
environment="Environment",
component="Component",
phase="optional-phase",
)
angles_reporter.add_artifacts([
Artifact(groupId="angles-ui", artifactId="anglesHQ", version="1.0.0")
])
angles_reporter.start_test(title="test1", suite="suite1")
angles_reporter.add_action("My first action")
platform = ScreenshotPlatform(
platformName="Android",
platformVersion="10",
browserName="Chrome",
browserVersion="89.0",
deviceName="Samsung Galaxy S9",
)
screenshot = angles_reporter.save_screenshot_with_platform(
file_path="/path/to/screenshot.png",
view="view_1",
tags=["smoke", "home"],
platform=platform,
)
angles_reporter.info_with_screenshot("Checking my view on android", screenshot.get("_id"))
angles_reporter.pass_step("Assertion", expected="true", actual="true", info="Just doing an assertion")
angles_reporter.fail_step("Assertion", expected="true", actual="false", info="Just doing an assertion")
execution = angles_reporter.save_test()
Attachments
A test can attach files to its results: console logs, network HAR files, videos, Playwright traces, page HTML snapshots and images. Angles shows each one on the test (or the step) with a viewer that suits it. The file extension decides how it is shown, so keep the real one: .log/.txt, .json, .har, .webm/.mp4, .zip (shown as a Playwright trace when the name contains "trace"), .html/.htm, .png/.jpg/.jpeg/.gif/.webp. Requires an Angles server with test attachment support.
angles_reporter.fail_step("Order confirmation", "Order confirmed", "Payment declined", "")
# attach to the step you just reported, e.g. the page as it was when the assertion failed
angles_reporter.attach_data_to_last_step(page.content(), "page.html")
angles_reporter.attach_file_to_last_step("artifacts/failure.png")
# attach to the whole test
angles_reporter.attach_file(page.video.path(), "checkout.webm")
angles_reporter.attach_file("artifacts/trace.zip")
angles_reporter.attach_file("artifacts/network.har")
angles_reporter.attach_data("\n".join(console_lines), "console.log")
angles_reporter.save_test()
Uploads happen straight away (they only need the build id), so this works in batch mode too. A rejected upload (e.g. an unsupported extension) raises AnglesApiError.
Batch mode
By default every call to save_test() sends the test execution to the Angles API straight away. If you'd rather send the whole test run in a single request at the end (e.g. for large runs), you can enable batch mode. The build is still created up-front and screenshots are still uploaded individually as the tests run (they need the build id), but the executions are gathered by the reporter until you call save_all_tests().
angles_reporter.set_batch_mode(True)
angles_reporter.start_build(name="TestRunName", team="Team", environment="Environment", component="Component")
# run your tests as usual: start_test(), save_screenshot(), pass_step()/fail_step() and save_test()
# save_test() now stores the executions in the reporter rather than sending them.
# once all tests are done, store all the executions against the build in one request.
updated_build = angles_reporter.save_all_tests()
Independent reporters for isolated state
Create AnglesReporter(...) instances directly when you need more than one live reporter at once, for example when publishing multiple builds or environments in parallel. Each instance keeps its own current_build, current_execution, and current_action state.
from angles_python_client import AnglesReporter
reporter_gib = AnglesReporter(base_url="https://angles-api.example/rest/api/v1.0/")
reporter_games_dev = AnglesReporter(base_url="https://angles-api.example/rest/api/v1.0/")
reporter_gib.start_build(
name="[suite] test-suite integration",
team="some-team",
environment="integration",
component="some-component",
)
reporter_games_dev.start_build(
name="[suite] test-suite dev",
team="some-team",
environment="dev",
component="some-component",
)
AnglesReporter.get_instance() and the module-level angles_reporter still return the shared convenience singleton.
AnglesReporter.get_instance_with_base_url(...) is kept for backward compatibility, but it now returns a fresh reporter bound to that base URL instead of reusing shared mutable reporting state.
Direct requests usage
from angles_python_client import AnglesHttpClient
from angles_python_client.requests import BuildRequests
http = AnglesHttpClient(base_url="http://127.0.0.1:3000/rest/api/v1.0/")
builds = BuildRequests(http)
build = builds.get_build("your-build-id")
Publish a release to PyPI
-
Bump
project.versioninpyproject.toml -
Push a tag like
v1.0.1:git tag v1.0.1 git push origin v1.0.1
The workflow .github/workflows/publish.yml will build and publish to PyPI.
Publish to TestPyPI first (optional)
-
Push a tag like
test-v1.0.1, or run thePublish to TestPyPIworkflow manually. -
Install from TestPyPI to validate:
python -m pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple angles-python-client
Build locally (manual)
python -m pip install -U pip build twine
python -m build
python -m twine check dist/*
python -m twine upload dist/*
Versioning
This project uses a standard pyproject.toml version = "X.Y.Z" field.
Bump version locally (and create a tag)
pip install -U bump2version
bump2version patch # or minor / major
git push --follow-tags
Bump via GitHub Actions (and publish)
Run the Bump version and tag workflow (Actions tab) and choose:
target=pypi→ creates a tag likev1.0.1(triggers the PyPI publish workflow)target=testpypi→ creates a tag liketest-v1.0.1(triggers the TestPyPI publish workflow)
Auto-release on main/master
This repo includes an optional workflow: .github/workflows/release-on-main.yml.
When enabled (it is committed by default), every push to main or master will:
- Read the current
project.versionfrompyproject.toml - Create and push a git tag
vX.Y.Z(if it doesn't already exist) - Build and publish to PyPI (Trusted Publishing)
- Bump the version patch for the next release and push that commit back to the default branch
To avoid loops, the post-bump commit includes [skip release] and the workflow ignores commits containing that marker.
Metadata
Release files for angles-python-client 1.0.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| angles_python_client-1.0.14.tar.gz | 26.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| angles_python_client-1.0.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.0 kB
Release files / angles_python_client-1.0.14.tar.gz
| Download URL | angles_python_client-1.0.14.tar.gz |
|---|---|
| Size | 26.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cb45c238e10276802e6447aa249fdfbb4f851e92d5dd8592da68dcfc7c6438e4
|
|
BLAKE2b-256 checksum How to use checksums |
3dc6608c88516e230d45b10e817474528ed9ceda8148cd14e82fbd664ca2ae91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / angles_python_client-1.0.14-py3-none-any.whl
| Download URL | angles_python_client-1.0.14-py3-none-any.whl |
|---|---|
| Size | 27.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
240833375ef302239f2547edbe620e191bdc05daf53743f9da1f1e0899b15ade
|
|
BLAKE2b-256 checksum How to use checksums |
50907c83413b13d39ac99ba06e19bf4e1db15a9ff754c191d3cf4a7056c0c8ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log