Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
660c182
feat(statcalc): add StatCalc module, fix bugs, update docs, bump to 1…
MarTrepodi Mar 3, 2026
db474a4
feat(async): add async client, refactor architecture, harden security
MarTrepodi Mar 3, 2026
cc18d47
feat(docs): add migration guide and update README with upgrade steps
MarTrepodi Mar 3, 2026
56f7507
chore(version): bump to 2.0.1rc1 and update changelog
MarTrepodi Mar 3, 2026
b4c714f
feat(examples): replace threaded player fetch example with modern asy…
MarTrepodi Mar 7, 2026
420a528
feat(statcalc): introduce dynamic GameDataBuilder for improved data l…
MarTrepodi Mar 7, 2026
099d5d7
refactor(helpers): split monolith into subpackage, add migration CLI
MarTrepodi Mar 7, 2026
8f6369a
feat(helpers): implement aggregated datacron dismantle materials calc…
MarTrepodi Mar 7, 2026
3c1f5cb
refactor(helpers): consolidate stat data imports and cleanup redundan…
MarTrepodi Mar 7, 2026
5e005f5
feat(tests): add integration tests for HMAC and async workflows, enha…
MarTrepodi Mar 7, 2026
1901aa4
refactor(helpers): replace `sentinels` dependency with custom lightwe…
MarTrepodi Mar 7, 2026
7c140ee
feat(docs): add Helpers and Exceptions API reference, update mkdocs.yml
MarTrepodi Mar 7, 2026
91df92e
refactor(helpers): remove `OPTIONAL` and `NotSet` sentinels, improve …
MarTrepodi Mar 7, 2026
3c55746
fix(hmac): serialize empty payload as empty string for comlink v4 com…
MarTrepodi Mar 7, 2026
0af1b84
chore(version): bump version to 2.0.2rc1
MarTrepodi Mar 7, 2026
37cf69a
fix(ci): improve service readiness checks in integration workflow
MarTrepodi Mar 7, 2026
d9c3466
chore(ci): update workflows with new scopes, Python versions, and rea…
MarTrepodi Mar 7, 2026
e606198
chore(ci): update branch filters and remove strict doc build flag
MarTrepodi Mar 7, 2026
d84ff2c
refactor: enhance type annotations and add stricter runtime checks
MarTrepodi Mar 7, 2026
c6b1e2e
refactor(tests): simplify HMAC exception handling and remove unused i…
MarTrepodi Mar 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI

on:
pull_request:
branches: [main, 2.0-development]
branches: [main, 1.0-maintenance, 2.0-development]
push:
branches: [main]

Expand Down Expand Up @@ -99,6 +99,27 @@ jobs:
name: coverage-report
path: coverage.xml

# ── Docs build ────────────────────────────────────────────────────────
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: uv pip install --system -e "." mkdocs-material "mkdocstrings[python]>=0.28.0"

- name: Build docs
run: mkdocs build

# ── Build verification ─────────────────────────────────────────────────
build:
name: Build
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/commit-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Commit Lint

on:
pull_request:
types: [opened, synchronize, reopened, edited]

permissions:
contents: read

jobs:
commitlint:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Lint commits
uses: wagoid/commitlint-github-action@v6
with:
configFile: commitlint.config.cjs
firstParent: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 4 additions & 2 deletions .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Commit Lint

on:
pull_request:
branches: [main, 2.0-development]
branches: [main, 1.0-maintenance]

permissions:
contents: read
Expand Down Expand Up @@ -30,7 +30,9 @@ jobs:
"chore", "docs", "test", "style", "ci", "perf"
]],
"scope-enum": [1, "always", [
"core", "helpers", "deps", "release", "ci"
"core", "helpers", "deps", "release", "ci",
"version", "hmac", "docs", "tests", "examples",
"async", "statcalc"
]],
"subject-max-length": [1, "always", 100]
}
Expand Down
97 changes: 97 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Integration Tests

on:
pull_request:
branches: [main, 1.0-maintenance]
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: integration-${{ github.ref }}
cancel-in-progress: true

jobs:
integration:
name: Integration Tests
runs-on: ubuntu-latest
services:
comlink:
image: ghcr.io/swgoh-utils/swgoh-comlink:latest
env:
APP_NAME: comlink-python-integration-tests
ports:
- 3000:3000
healthcheck:
test: [ "CMD", "/swgoh-comlink", "--check" ]
start_period: 10s
start_interval: 0.5s

comlink-hmac:
image: ghcr.io/swgoh-utils/swgoh-comlink:latest
env:
APP_NAME: comlink-python-hmac-integration-tests
ACCESS_KEY: test_public_key
SECRET_KEY: test_secret_key
ports:
- 3001:3000
healthcheck:
test: [ "CMD", "/swgoh-comlink", "--check" ]
start_period: 10s
start_interval: 0.5s

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: uv pip install --system -e "." pytest pytest-asyncio

- name: Wait for Comlink services
run: |
comlink_ready=false
for i in $(seq 1 30); do
if curl -sf http://localhost:3000/readyz > /dev/null 2>&1; then
comlink_ready=true
echo "✓ comlink is ready"
break
fi
echo "Waiting for Comlink... ($i/30)"
sleep 2
done
if [ "$comlink_ready" != "true" ]; then
echo "::error::Comlink service failed to start within 60 seconds"
docker ps -a
exit 1
fi

hmac_ready=false
for i in $(seq 1 30); do
if curl -sf http://localhost:3001/readyz > /dev/null 2>&1; then
hmac_ready=true
echo "✓ comlink is ready"
break
fi
echo "Waiting for Comlink HMAC... ($i/30)"
sleep 2
done
if [ "$hmac_ready" != "true" ]; then
echo "::error::Comlink HMAC service failed to start within 60 seconds"
docker ps -a
exit 1
fi

- name: Run integration tests
env:
RUN_INTEGRATION_TESTS: "1"
run: python -m pytest tests/integration/ -v
35 changes: 35 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Test

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Setup uv
uses: astral-sh/setup-uv@v3

- name: Sync dependencies
run: uv sync --group dev --group docs

- name: Run unit tests
run: uv run pytest -q

- name: Build docs
run: uv run mkdocs build
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ coverage.xml
*.py,cover
.hypothesis/
.pytest_cache/
.ruff_cache/
.parity-cache/
parity/.cache-gameData.json
cover/


Expand Down
136 changes: 136 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,142 @@

<!-- insertion marker -->

## [v2.0.0 Pending Release] - feature/async

### Breaking Changes

- remove `OPTIONAL` and `NotSet` sentinel exports from `swgoh_comlink.helpers`.
Replace any usage with plain `None` defaults or `int` defaults as appropriate.
- remove external `sentinels` library dependency. The package now uses an inline
`Sentinel` class. Code importing sentinels from `swgoh_comlink.helpers` should
remove references to `OPTIONAL` and `NotSet`.
- change `get_gac_brackets()` and `async_get_gac_brackets()` `limit` parameter
from sentinel-based default to `int` with default `0` (meaning no limit).

### Bug Fixes

- fix HMAC empty payload serialization to use empty string (`""`) instead of
empty object (`{}`) for compatibility with comlink v4 (#51).

### Features

- add `SwgohComlinkAsync` async client with full API parity to `SwgohComlink`.
Both clients inherit from a shared `SwgohComlinkBase` class.
- add `StatCalcAsync` async stat calculator with `create()` factory method for
non-blocking game data initialization. Inherits all calculation methods from
`StatCalc`.
- add `GameDataBuilder` / `GameDataBuilderAsync` to build StatCalc game data
dynamically from a running Comlink service instead of fetching a static file
from GitHub.
- replace `requests` library with `httpx` for both sync and async HTTP support.
- add connection pooling via persistent `httpx.Client` / `httpx.AsyncClient` instances.
- add context manager support (`with SwgohComlink()` and `async with SwgohComlinkAsync()`).
- add async helper variants: `async_get_current_gac_event()`, `async_get_gac_brackets()`,
and `async_get_guild_members()` for use with `SwgohComlinkAsync`.
- add exponential probing with binary search for GAC bracket boundary discovery,
reducing HTTP requests from O(n) to O(log n).
- add parallel batch fetching via `asyncio.gather` in `async_get_gac_brackets()`
for significantly faster bracket collection.
- add comprehensive Helpers API reference and Exceptions documentation pages.

### Code Refactoring

- replace external `sentinels` library with inline `Sentinel` class; remove
unused sentinels (`OPTIONAL`, `NotSet`, `EMPTY`, `NotGiven`, `SET`,
`MutualRequiredNotSet`).
- extract shared logic (HMAC auth, payload builders, URL sanitization, param_alias decorator)
into `_base.py` base class.
- unify all HTTP communication through a single `_request()` gateway method
in both sync and async clients.
- refactor monolithic `helpers.py` (1,970 lines) into a focused `helpers/` subpackage
with domain-specific modules (`_arena.py`, `_gac.py`, `_game_data.py`, `_guild.py`,
`_omicron.py`, `_utils.py`, `_decorators.py`, `_sentinels.py`, `_data_items.py`,
`_stat_data.py`, `_constants.py`). All existing import paths are preserved via
backward-compatible re-export shim in `helpers/__init__.py`.
- consolidate 4 duplicate copies of stat data (Constants.STAT_ENUMS,
Constants.UNIT_STAT_ENUMS_MAP, Constants.STATS, StatCalc.STATS_NAME_MAP) into a
single canonical `STATS` dict in `helpers/_stat_data.py` with derived views.
- replace 489-line inline `STATS_NAME_MAP` dict in `StatCalc/calculator.py` with
import from `helpers/_stat_data`.

### Dependencies

- replace `requests>=2.32.4` with `httpx>=0.28`.
- add `pytest-httpx>=0.35` and `pytest-asyncio>=0.24` to dev dependencies.

### Logging

- refactor logging to follow Python library best practice: attach only `NullHandler`
to the package root logger; remove forced `StreamHandler` and level configuration.
- remove unused logger instances from `_base.py`, `swgoh_comlink.py`, and
`swgoh_comlink_async.py`.
- switch `exceptions.py` and `helpers.py` to use `logging.getLogger(__name__)` directly.
- keep `LoggingFormatter` as an opt-in convenience in `globals.py`.
- rewrite `docs/logging.md` for the new approach.

### Tools

- add `swgoh-migrate` CLI tool (`python -m swgoh_comlink.migrate`) for scanning
user codebases and identifying deprecated import patterns, API changes, and
migration steps needed when upgrading from v1.x. Supports `--severity`,
`--no-color`, and `--exclude` options.

### Documentation

- add migration guide (`docs/migration.md`) covering dependency changes, exception
handling, logging configuration, and client lifecycle.
- add migration summary section to README with link to the full guide.

### Testing

- rewrite unit tests to use `pytest-httpx` mocking instead of `monkeypatch`.
- add comprehensive async client test suite mirroring sync coverage.
- add `test_base.py` with tests for base class utilities, HMAC, payload builders,
and validation logic.
- increase test coverage from 38% to 48% (100% on core modules `_base.py`,
`swgoh_comlink.py`, and `swgoh_comlink_async.py`).

---

## [v1.18.0rc1](https://github.com/swgoh-utils/comlink-python/releases/tag/v1.18.0rc1) - 2026-03-03

<small>[Compare with v1.17.0](https://github.com/swgoh-utils/comlink-python/compare/v1.17.0...v1.18.0rc1)</small>

### Features

- add StatCalc module for local stat and GP calculation without an external
swgoh-stats service ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).

### Bug Fixes

- remove duplicate `_rename_stats` call in `calc_char_stats` that caused
`AttributeError` on second pass ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).
- fix `calc_player_stats` type annotations, `isinstance` syntax, and list
mutation bug ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).
- remove stray `print()` statements and unnecessary `deepcopy` in
`_rename_stats` ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).

### Documentation

- expand StatCalc usage guide in README and mkdocs API
reference ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).
- add missing `get_name_spaces` and `get_segmented_content` methods to README
table ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).
- update CONTRIBUTING.md project structure and key modules for StatCalc and
test subdirectories ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).

### Chores

- remove unused `scripts/verify-upstream.sh` ([a880097](https://github.com/swgoh-utils/comlink-python/commit/a880097889b30e345c80ec99ff207d4e50daa431) by
MarTrepodi).

## [v1.17.0](https://github.com/swgoh-utils/comlink-python/releases/tag/v1.17.0) - 2025-11-18

<small>[Compare with v1.16.0](https://github.com/swgoh-utils/comlink-python/compare/v1.16.0...v1.17.0)</small>
Expand Down
Loading
Loading