Skip to content

Commit 88cd0d2

Browse files
authored
High-level Client with Image Handling etc. (#5)
1 parent e0a2c0b commit 88cd0d2

74 files changed

Lines changed: 9769 additions & 92 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.coverage

52 KB
Binary file not shown.

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "uv"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/build_and_test.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
steps:
1616
- name: Checkout code
17-
uses: actions/checkout@v3
17+
uses: actions/checkout@v4
1818

1919
- name: Initialize submodules
2020
env:
@@ -72,7 +72,19 @@ jobs:
7272
7373
- name: Run tests
7474
run: |
75-
uv run pytest
75+
uv run pytest --junitxml=pytest.xml --tb=auto --cov-report=term-missing:skip-covered --cov=src tests/ | tee pytest-coverage.txt
76+
77+
- name: Pytest Coverage Comment
78+
uses: MishaKav/pytest-coverage-comment@v1.1.56
79+
with:
80+
junitxml-path: ./pytest.xml
81+
82+
- name: Upload test results
83+
uses: actions/upload-artifact@v4 # upload test results
84+
if: ${{ !cancelled() }} # run this step even if previous step failed
85+
with:
86+
name: test-results
87+
path: pytest.xml
7688

7789
- name: Build package
7890
run: |

.github/workflows/docs.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Build and Deploy Documentation
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
paths:
7+
- "docs/**"
8+
- "src/**"
9+
- "examples/**"
10+
- "README.md"
11+
- "pyproject.toml"
12+
- ".github/workflows/docs.yml"
13+
pull_request:
14+
branches: [main, master]
15+
paths:
16+
- "docs/**"
17+
- "src/**"
18+
- "examples/**"
19+
- "README.md"
20+
- "pyproject.toml"
21+
- ".github/workflows/docs.yml"
22+
workflow_dispatch:
23+
inputs:
24+
reason:
25+
description: "Reason for manual documentation build"
26+
required: false
27+
default: "Manual trigger"
28+
29+
permissions:
30+
contents: read
31+
pages: write
32+
id-token: write
33+
34+
concurrency:
35+
group: "pages"
36+
cancel-in-progress: false
37+
38+
jobs:
39+
build:
40+
runs-on: ubuntu-latest
41+
steps:
42+
- name: Checkout
43+
uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0
46+
47+
- name: Install uv
48+
uses: astral-sh/setup-uv@v6
49+
with:
50+
enable-cache: true
51+
52+
- name: Set up Python
53+
run: uv python install
54+
55+
- name: Install dependencies
56+
run: uv sync --locked --group docs
57+
58+
- name: Build documentation
59+
run: |
60+
cd docs
61+
uv run make clean
62+
uv run make html
63+
64+
- name: Setup Pages
65+
uses: actions/configure-pages@v4
66+
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
67+
68+
- name: Upload artifact
69+
uses: actions/upload-pages-artifact@v3
70+
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
71+
with:
72+
path: docs/_build/html
73+
74+
- name: Upload build artifacts for debugging
75+
uses: actions/upload-artifact@v4
76+
if: failure()
77+
with:
78+
name: docs-build-artifacts
79+
path: |
80+
docs/_build/
81+
docs/*.log
82+
83+
deploy:
84+
environment:
85+
name: github-pages
86+
url: ${{ steps.deployment.outputs.page_url }}
87+
runs-on: ubuntu-latest
88+
needs: build
89+
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
90+
steps:
91+
- name: Deploy to GitHub Pages
92+
id: deployment
93+
uses: actions/deploy-pages@v4

.github/workflows/test_report.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: "Test Report"
2+
on:
3+
workflow_run:
4+
workflows: ["Build and Test"]
5+
types:
6+
- completed
7+
8+
permissions:
9+
contents: read
10+
actions: read
11+
checks: write
12+
13+
jobs:
14+
report:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: dorny/test-reporter@v2
18+
with:
19+
artifact: test-results
20+
name: Tests
21+
path: "*.xml"
22+
reporter: java-junit

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ wheels/
88

99
# Virtual environments
1010
.venv
11+
.env
12+
13+
docs/_build/

AGENTS.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# AGENTS.md
2+
3+
## Setup commands
4+
- Install deps: `uv sync --dev`
5+
- Build package: `uv build`
6+
- Run tests: `pytest`
7+
- Type check code: `pyright`
8+
- Format code: `ruff format`
9+
- Lint code: `ruff check`
10+
- Install git hooks: `pre-commit install`
11+
- Compile protobufs: `bash scripts/compile_proto.sh` (run from root)
12+
13+
## Code style
14+
- Use Python type hints throughout
15+
- Follow Black formatting (via ruff)
16+
- Async/await for I/O operations
17+
- Document public APIs with docstrings
18+
- Use functional patterns where possible
19+
- Implement proper error handling
20+
21+
## Testing instructions
22+
- Tests live in the `tests/` directory
23+
- Run `pytest` for full test suite
24+
- Run `pytest path/to/test.py` for specific tests
25+
- Run `pytest -k "test_name"` to run by pattern
26+
- Run `pytest --cov=src/athena_client` for coverage
27+
- Add tests for all new code
28+
- Mock external services in tests
29+
- Test both success and error cases
30+
31+
## PR instructions
32+
- Title format: [component] Description
33+
- Run `ruff check`, `pyright`, and `pytest` before committing
34+
- Keep PRs focused on a single change
35+
- Add tests for new functionality
36+
- Update documentation for API changes
37+
- Add proper type hints
38+
39+
## Dev tips
40+
- Use `uv` package manager instead of pip
41+
- Don't use `uv pip` commands, just the base `uv` commands
42+
- Run formatters before committing
43+
- Check generated code in `src/athena_client/generated/`
44+
- Add error handling at each pipeline stage
45+
- Use correlation IDs for request tracing
46+
47+
## Documentation
48+
- Docs are in `docs/`
49+
- Build docs by `cd docs && make clean && make html`

README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,79 @@
33
This is a Python library for interacting with the Athena API (Resolver Unknown
44
CSAM Detection).
55

6+
## Authentication
7+
8+
The Athena client supports two authentication methods:
9+
10+
### Static Token Authentication
11+
```python
12+
from athena_client.client.channel import create_channel
13+
14+
# Use a pre-existing authentication token
15+
channel = create_channel(host="your-host", auth_token="your-token")
16+
```
17+
18+
### OAuth Credential Helper (Recommended)
19+
The credential helper automatically handles OAuth token acquisition and refresh:
20+
21+
```python
22+
import asyncio
23+
from athena_client.client.channel import CredentialHelper, create_channel_with_credentials
24+
25+
async def main():
26+
# Create credential helper with OAuth settings
27+
credential_helper = CredentialHelper(
28+
client_id="your-oauth-client-id",
29+
client_secret="your-oauth-client-secret",
30+
auth_url="https://crispthinking.auth0.com/oauth/token", # Optional, this is default
31+
audience="crisp-athena-dev" # Optional, this is default
32+
)
33+
34+
# Create channel with automatic OAuth handling
35+
channel = await create_channel_with_credentials(
36+
host="your-host",
37+
credential_helper=credential_helper
38+
)
39+
40+
asyncio.run(main())
41+
```
42+
43+
#### Environment Variables
44+
For the OAuth example to work, set these environment variables:
45+
```bash
46+
export OAUTH_CLIENT_ID="your-client-id"
47+
export OAUTH_CLIENT_SECRET="your-client-secret"
48+
export ATHENA_HOST="your-athena-host"
49+
```
50+
51+
#### OAuth Features
52+
- **Automatic token refresh**: Tokens are automatically refreshed when they expire
53+
- **Thread-safe**: Multiple concurrent requests will safely share cached tokens
54+
- **Error handling**: Comprehensive error handling for OAuth failures
55+
- **Configurable**: Custom OAuth endpoints and audiences supported
56+
57+
See `examples/oauth_example.py` for a complete working example.
58+
59+
## Examples
60+
61+
- `examples/example.py` - Basic classification example with static token
62+
- `examples/oauth_example.py` - OAuth authentication with credential helper
63+
- `examples/create_image.py` - Image generation utilities
64+
65+
## TODO
66+
67+
### Async pipelines
68+
Make pipeline style invocation of the async interators such that we can
69+
70+
async read file -> async transform -> async classify -> async results
71+
72+
### More async pipeline transformers
73+
Add additional pipeline transformers for:
74+
- Image format conversion
75+
- Metadata extraction
76+
- Error recovery and retry
77+
78+
679

780
## Development
881
This package uses [uv](https://docs.astral.sh/uv/) to manage its packages.

athena-protobufs

docs/Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Minimal makefile for Sphinx documentation
2+
3+
# You can set these variables from the command line, and also
4+
# from the environment for the first two.
5+
SPHINXOPTS ?=
6+
SPHINXBUILD ?= sphinx-build
7+
SOURCEDIR = .
8+
BUILDDIR = _build
9+
10+
# Put it first so that "make" without argument is like "make help".
11+
help:
12+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13+
14+
.PHONY: help Makefile clean
15+
16+
# Clean the build directory
17+
clean:
18+
rm -rf $(BUILDDIR)/*
19+
20+
# Catch-all target: route all unknown targets to Sphinx using the new
21+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
22+
%: Makefile
23+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

0 commit comments

Comments
 (0)