hvbattle 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -eu
3
+
4
+ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ exec "$repo_root/scripts/hooks/finalize-markdown.sh"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -eu
3
+
4
+ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ exec "$repo_root/scripts/hooks/finalize-python.sh"
@@ -0,0 +1,46 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read(**/*)",
5
+ "Write(**/*)",
6
+ "Edit(**/*)",
7
+ "Bash(docker:*)",
8
+ "Bash(ls:*)",
9
+ "Bash(mkdir:*)",
10
+ "Bash(tree:*)",
11
+ "Bash(find:*)",
12
+ "Bash(uv:*)",
13
+ "Bash(grep:*)",
14
+ "Bash(xargs cat)",
15
+ "Bash(git diff:*)",
16
+ "Bash(git -C * diff:*)",
17
+ "Bash(cat > *)",
18
+ "Bash(git add *)",
19
+ "Bash(git commit -m ' *)",
20
+ "Bash(uv run *)",
21
+ "Bash(uv run python -c ' *)",
22
+ "Bash(python3 -)",
23
+ "Bash(python3 -c ' *)",
24
+ "Bash(echo \"exit: $?\")"
25
+ ],
26
+ "additionalDirectories": [
27
+ "/tmp"
28
+ ]
29
+ },
30
+ "hooks": {
31
+ "Stop": [
32
+ {
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "command": "scripts/hooks/finalize-python.sh"
37
+ },
38
+ {
39
+ "type": "command",
40
+ "command": "scripts/hooks/finalize-markdown.sh"
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+ }
46
+ }
@@ -0,0 +1,63 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: [pyproject.toml]
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 2
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.14"
22
+
23
+ - name: Install version checker
24
+ run: python -m pip install packaging
25
+
26
+ - name: Check version bump
27
+ id: version
28
+ run: |
29
+ CURRENT=$(python -c "
30
+ import tomllib
31
+ with open('pyproject.toml', 'rb') as f:
32
+ print(tomllib.load(f)['project']['version'])
33
+ ")
34
+ if git cat-file -e HEAD~1:pyproject.toml 2>/dev/null; then
35
+ PREVIOUS=$(git show HEAD~1:pyproject.toml | python -c "
36
+ import tomllib, sys
37
+ print(tomllib.load(sys.stdin.buffer)['project']['version'])
38
+ ")
39
+ else
40
+ PREVIOUS=""
41
+ fi
42
+ echo "current=$CURRENT" >> "$GITHUB_OUTPUT"
43
+ echo "previous=$PREVIOUS" >> "$GITHUB_OUTPUT"
44
+ if [ -z "$PREVIOUS" ]; then
45
+ echo "bumped=true" >> "$GITHUB_OUTPUT"
46
+ elif [ "$CURRENT" != "$PREVIOUS" ]; then
47
+ python -c "
48
+ from packaging.version import Version
49
+ current, previous = Version('$CURRENT'), Version('$PREVIOUS')
50
+ exit(0 if current > previous else 1)
51
+ "
52
+ echo "bumped=true" >> "$GITHUB_OUTPUT"
53
+ else
54
+ echo "bumped=false" >> "$GITHUB_OUTPUT"
55
+ fi
56
+
57
+ - name: Build
58
+ if: steps.version.outputs.bumped == 'true'
59
+ run: pip install build && python -m build
60
+
61
+ - name: Publish
62
+ if: steps.version.outputs.bumped == 'true'
63
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,9 @@
1
+ {
2
+ "recommendations": [
3
+ "ms-python.python",
4
+ "charliermarsh.ruff",
5
+ "ms-python.black-formatter",
6
+ "ms-python.mypy-type-checker",
7
+ "DavidAnson.vscode-markdownlint"
8
+ ]
9
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "python.analysis.typeCheckingMode": "off",
3
+ "python.analysis.diagnosticSeverityOverrides": {
4
+ "reportMissingModuleSource": "none",
5
+ "reportMissingImports": "none"
6
+ },
7
+ "editor.formatOnSave": true,
8
+ "[python]": {
9
+ "editor.defaultFormatter": "ms-python.black-formatter",
10
+ "editor.codeActionsOnSave": {
11
+ "source.fixAll.ruff": "always"
12
+ }
13
+ },
14
+ "black-formatter.importStrategy": "fromEnvironment",
15
+ "ruff.importStrategy": "fromEnvironment",
16
+ "[markdown]": {
17
+ "editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
18
+ },
19
+ "files.trimTrailingWhitespace": true,
20
+ "files.insertFinalNewline": true,
21
+ "editor.rulers": [
22
+ 88
23
+ ],
24
+ "mypy-type-checker.importStrategy": "fromEnvironment",
25
+ "mypy-type-checker.args": [
26
+ "--config-file=mypy.ini"
27
+ ]
28
+ }
@@ -0,0 +1,14 @@
1
+ # Agent Instructions
2
+
3
+ The repository keeps provider-neutral finalization scripts in `scripts/hooks/`.
4
+ Do not create separate copies under an individual agent's configuration
5
+ directory.
6
+
7
+ - Before development, create a clean environment with
8
+ `bash scripts/rebuild-env.sh`.
9
+ - After changing Python, run `bash scripts/hooks/finalize-python.sh`.
10
+ - After changing Markdown, run `bash scripts/hooks/finalize-markdown.sh`.
11
+ - Keep the committed dependency source for `hvbrowser` on PyPI. Install local
12
+ editable checkouts manually, in dependency order, only after rebuilding the
13
+ environment.
14
+ - Automated tests must remain offline and must never start or flee a battle.
@@ -0,0 +1,76 @@
1
+ Metadata-Version: 2.4
2
+ Name: hvbattle
3
+ Version: 0.1.0
4
+ Summary: Reusable battle-domain APIs for HentaiVerse.
5
+ Project-URL: Homepage, https://github.com/Kuan-Lun/hvbattle
6
+ Project-URL: Tracker, https://github.com/Kuan-Lun/hvbattle/issues
7
+ Author: Kuan-Lun Wang
8
+ License: GNU Affero General Public License v3
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Python: <3.15,>=3.14
15
+ Requires-Dist: hv-bie>=0.7.0
16
+ Requires-Dist: hvbrowser<0.2,>=0.1.0
17
+ Requires-Dist: ponychart-classifier>=0.7.0
18
+ Requires-Dist: zendriver<0.16,>=0.15.5
19
+ Provides-Extra: dev
20
+ Requires-Dist: black>=26.5.1; extra == 'dev'
21
+ Requires-Dist: mypy>=2.1.0; extra == 'dev'
22
+ Requires-Dist: pymarkdownlnt>=0.9.38; extra == 'dev'
23
+ Requires-Dist: pytest>=9.1.1; extra == 'dev'
24
+ Requires-Dist: ruff>=0.15.20; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # HVBattle
28
+
29
+ HVBattle provides reusable HentaiVerse battle-domain APIs. It builds on
30
+ `hvbrowser` for the authenticated Hentaiverse browser session and keeps the
31
+ private command-line runner in a separate application workspace.
32
+
33
+ The first release preserves the historical `BattleDriver` API while adding a
34
+ safe `run_current()` boundary. That method only runs an already active battle;
35
+ it never repairs equipment, recovers stamina, or starts Arena/GrindFest.
36
+ Automatic next-battle toggles default to off and require explicit opt-in.
37
+ `BattleDriver` preloads the PonyChart classifier and ONNX model before opening
38
+ the browser, so a timed challenge never pays the first-load cost.
39
+
40
+ ```python
41
+ import asyncio
42
+
43
+ from hvbattle import BattleDriver
44
+
45
+
46
+ async def main() -> None:
47
+ async with BattleDriver(headless=True) as driver:
48
+ await driver.run_current()
49
+
50
+
51
+ asyncio.run(main())
52
+ ```
53
+
54
+ The legacy `battle()` loop remains available for the private runner. It can
55
+ repair equipment and recover stamina; starting another Arena or GrindFest also
56
+ requires explicitly enabling the corresponding auto-next option.
57
+
58
+ ## Development
59
+
60
+ Build a clean environment backed by PyPI releases:
61
+
62
+ ```bash
63
+ bash scripts/rebuild-env.sh
64
+ ```
65
+
66
+ For coordinated local development before all dependent releases are on PyPI,
67
+ overlay editable checkouts in dependency order:
68
+
69
+ ```bash
70
+ uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
71
+ /Users/kuanlun_wang/Desktop/git-repo/hbrowser.clone
72
+ uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
73
+ /Users/kuanlun_wang/Desktop/git-repo/hvbrowser.clone
74
+ ```
75
+
76
+ Commands that must preserve these editable overlays use `uv run --no-sync`.
@@ -0,0 +1,50 @@
1
+ # HVBattle
2
+
3
+ HVBattle provides reusable HentaiVerse battle-domain APIs. It builds on
4
+ `hvbrowser` for the authenticated Hentaiverse browser session and keeps the
5
+ private command-line runner in a separate application workspace.
6
+
7
+ The first release preserves the historical `BattleDriver` API while adding a
8
+ safe `run_current()` boundary. That method only runs an already active battle;
9
+ it never repairs equipment, recovers stamina, or starts Arena/GrindFest.
10
+ Automatic next-battle toggles default to off and require explicit opt-in.
11
+ `BattleDriver` preloads the PonyChart classifier and ONNX model before opening
12
+ the browser, so a timed challenge never pays the first-load cost.
13
+
14
+ ```python
15
+ import asyncio
16
+
17
+ from hvbattle import BattleDriver
18
+
19
+
20
+ async def main() -> None:
21
+ async with BattleDriver(headless=True) as driver:
22
+ await driver.run_current()
23
+
24
+
25
+ asyncio.run(main())
26
+ ```
27
+
28
+ The legacy `battle()` loop remains available for the private runner. It can
29
+ repair equipment and recover stamina; starting another Arena or GrindFest also
30
+ requires explicitly enabling the corresponding auto-next option.
31
+
32
+ ## Development
33
+
34
+ Build a clean environment backed by PyPI releases:
35
+
36
+ ```bash
37
+ bash scripts/rebuild-env.sh
38
+ ```
39
+
40
+ For coordinated local development before all dependent releases are on PyPI,
41
+ overlay editable checkouts in dependency order:
42
+
43
+ ```bash
44
+ uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
45
+ /Users/kuanlun_wang/Desktop/git-repo/hbrowser.clone
46
+ uv pip install --python .venv/bin/python --reinstall --no-deps --editable \
47
+ /Users/kuanlun_wang/Desktop/git-repo/hvbrowser.clone
48
+ ```
49
+
50
+ Commands that must preserve these editable overlays use `uv run --no-sync`.
@@ -0,0 +1,28 @@
1
+ [mypy]
2
+ python_version = 3.14
3
+ warn_unused_configs = True
4
+ disallow_untyped_defs = True
5
+ check_untyped_defs = True
6
+ warn_redundant_casts = True
7
+ warn_unused_ignores = True
8
+ no_implicit_optional = True
9
+ strict_equality = True
10
+ warn_return_any = True
11
+ disallow_any_generics = True
12
+ disallow_subclassing_any = True
13
+ disallow_untyped_calls = True
14
+ disallow_incomplete_defs = True
15
+ disallow_untyped_decorators = True
16
+ no_implicit_reexport = True
17
+
18
+ [mypy-zendriver.*]
19
+ ignore_missing_imports = True
20
+
21
+ [mypy-hv_bie.*]
22
+ ignore_missing_imports = True
23
+
24
+ [mypy-ponychart_classifier.*]
25
+ ignore_missing_imports = True
26
+
27
+ [mypy-hvbattle.hv_battle_observer_pattern]
28
+ disable_error_code = override
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hvbattle"
7
+ version = "0.1.0"
8
+ description = "Reusable battle-domain APIs for HentaiVerse."
9
+ readme = "README.md"
10
+ authors = [{ name = "Kuan-Lun Wang" }]
11
+ license = { text = "GNU Affero General Public License v3" }
12
+ requires-python = ">=3.14,<3.15"
13
+ dependencies = [
14
+ "hvbrowser>=0.1.0,<0.2",
15
+ "hv-bie>=0.7.0",
16
+ "ponychart-classifier>=0.7.0",
17
+ "zendriver>=0.15.5,<0.16",
18
+ ]
19
+
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Intended Audience :: Developers",
23
+ "Operating System :: OS Independent",
24
+ "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
25
+ "Programming Language :: Python :: 3.14",
26
+ ]
27
+
28
+ [project.optional-dependencies]
29
+ dev = [
30
+ "black>=26.5.1",
31
+ "ruff>=0.15.20",
32
+ "mypy>=2.1.0",
33
+ "pymarkdownlnt>=0.9.38",
34
+ "pytest>=9.1.1",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/Kuan-Lun/hvbattle"
39
+ Tracker = "https://github.com/Kuan-Lun/hvbattle/issues"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/hvbattle"]
43
+
44
+ [tool.ruff]
45
+ line-length = 88
46
+
47
+ [tool.ruff.lint]
48
+ select = ["E", "F", "I", "UP"]
49
+ extend-ignore = ["E203", "E226", "E501"]
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ # Shared finalizer for Markdown changes.
3
+
4
+ set -uo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8
+ cd "$REPO_ROOT"
9
+
10
+ MD_FILES=()
11
+ while IFS= read -r file; do
12
+ MD_FILES+=("$file")
13
+ done < <(
14
+ find . -maxdepth 2 -type f -name "*.md" \
15
+ -not -path "./.venv/*" \
16
+ -not -path "./node_modules/*" \
17
+ -not -path "./.pytest_cache/*" \
18
+ -not -path "./.*" \
19
+ | sort
20
+ )
21
+
22
+ if [ ${#MD_FILES[@]} -eq 0 ]; then
23
+ exit 0
24
+ fi
25
+
26
+ uv run --no-sync pymarkdown fix "${MD_FILES[@]}" >/dev/null 2>&1 || true
27
+
28
+ if ! uv run --no-sync ruff format --preview "${MD_FILES[@]}" >&2; then
29
+ exit 2
30
+ fi
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+ # Shared finalizer for Python changes. `--no-sync` preserves manually
3
+ # installed editable dependency checkouts in the project environment.
4
+
5
+ set -eu
6
+ trap 'exit 2' ERR
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
10
+ cd "$REPO_ROOT"
11
+
12
+ FORMAT_PATHS=(src/hvbattle tests)
13
+ TYPE_PATHS=(src/hvbattle)
14
+
15
+ uv run --no-sync black "${FORMAT_PATHS[@]}" >&2
16
+ uv run --no-sync ruff check --fix "${FORMAT_PATHS[@]}" >&2
17
+ uv run --no-sync black "${FORMAT_PATHS[@]}" >&2
18
+ uv run --no-sync mypy "${TYPE_PATHS[@]}" >&2
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+ # Rebuild a clean development environment whose hvbrowser dependency comes
3
+ # from PyPI. Install local editable dependencies manually afterwards when
4
+ # cross-repository development is required.
5
+
6
+ set -euo pipefail
7
+ cd "$(dirname "$0")/.."
8
+
9
+ rm -rf .venv .mypy_cache .ruff_cache .pytest_cache
10
+ find . -type d -name __pycache__ -exec rm -rf {} +
11
+ uv cache clean --force
12
+ uv venv --python 3.14
13
+ uv pip install -e ".[dev]"
@@ -0,0 +1,20 @@
1
+ """Public battle-domain API."""
2
+
3
+ from hvbrowser.runtime import notify
4
+
5
+ from .hv_battle import BattleDriver
6
+ from .hv_battle_defaults import (
7
+ DEFAULT_FORBIDDEN_SKILLS,
8
+ DEFAULT_STATTHRESHOLD,
9
+ StatThreshold,
10
+ )
11
+ from .hv_battle_ponychart import preload_ponychart_classifier
12
+
13
+ __all__ = [
14
+ "BattleDriver",
15
+ "DEFAULT_FORBIDDEN_SKILLS",
16
+ "DEFAULT_STATTHRESHOLD",
17
+ "StatThreshold",
18
+ "notify",
19
+ "preload_ponychart_classifier",
20
+ ]