Skip to content

Commit 13404e1

Browse files
committed
feat: migrate to uv, bump to 0.1.0, prep for PyPI release
Switch build backend from hatchling to uv_build. Use PEP 735 [dependency-groups] for dev deps, PEP 639 license fields. Lefthook: parallel pre-commit (ruff format, ruff check on staged files with stage_fixed), parallel pre-push (ruff full, mypy, pytest). Release workflow: astral-sh/setup-uv, uv sync and uv build, re-enabled repository_dispatch and daily schedule triggers. Version bump updates pyproject.toml and version.py in lockstep.
1 parent 723bc72 commit 13404e1

8 files changed

Lines changed: 522 additions & 74 deletions

File tree

.github/workflows/release.yml

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: Release
22

33
on:
4-
# repository_dispatch:
5-
# types: [openapi-updated]
6-
# schedule:
7-
# - cron: '0 6 * * *'
4+
repository_dispatch:
5+
types: [openapi-updated]
6+
schedule:
7+
- cron: '0 6 * * *'
88
workflow_dispatch:
99
inputs:
1010
version_bump:
@@ -24,59 +24,62 @@ jobs:
2424
with:
2525
token: ${{ secrets.GITHUB_TOKEN }}
2626

27-
- uses: actions/setup-python@v5
27+
- uses: astral-sh/setup-uv@v7
2828
with:
2929
python-version: '3.12'
30+
enable-cache: true
3031

31-
- name: Install tools
32-
run: pip install hatch httpx
32+
- name: Install deps
33+
run: uv sync --all-extras --dev
3334

34-
- name: Fetch latest spec
35-
run: python generate.py
35+
- name: Regenerate SDK from live spec
36+
run: uv run python generate.py
3637

3738
- name: Check if spec changed
3839
id: diff
3940
run: |
40-
if git diff --quiet specs/openapi.json; then
41+
if git diff --quiet specs/openapi.json src/roxy_sdk/factory.py; then
4142
echo "changed=false" >> $GITHUB_OUTPUT
4243
else
4344
echo "changed=true" >> $GITHUB_OUTPUT
4445
fi
4546
46-
- name: Lint and typecheck
47+
- name: Lint
4748
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
48-
run: |
49-
pip install ruff mypy
50-
ruff check .
51-
mypy src/roxy_sdk/factory.py src/roxy_sdk/__init__.py
49+
run: uv run ruff check .
50+
51+
- name: Typecheck
52+
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
53+
run: uv run mypy src/roxy_sdk/__init__.py
5254

5355
- name: Test
5456
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
55-
run: |
56-
pip install -e . pytest pytest-asyncio
57-
pytest tests/test_factory.py -v
57+
run: uv run pytest tests/test_factory.py -v
5858

59-
- name: Bump version
59+
- name: Bump version in pyproject.toml and version.py
6060
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
6161
run: |
62-
python3 -c "
62+
python3 - <<'PY'
6363
import re
64-
bump = '${{ github.event.inputs.version_bump || 'patch' }}'
65-
path = 'src/roxy_sdk/version.py'
66-
text = open(path).read()
67-
ver = re.search(r'VERSION = \"(.+?)\"', text).group(1)
68-
parts = [int(x) for x in ver.split('.')]
69-
if bump == 'major': parts[0] += 1; parts[1] = 0; parts[2] = 0
70-
elif bump == 'minor': parts[1] += 1; parts[2] = 0
71-
else: parts[2] += 1
72-
new_ver = '.'.join(str(x) for x in parts)
73-
open(path, 'w').write(f'VERSION = \"{new_ver}\"\n')
74-
open('/tmp/new_version.txt', 'w').write(new_ver)
75-
"
64+
bump = "${{ github.event.inputs.version_bump || 'patch' }}"
65+
pp = open("pyproject.toml").read()
66+
ver = re.search(r'^version = "(.+?)"', pp, re.M).group(1)
67+
parts = [int(x) for x in ver.split(".")]
68+
if bump == "major": parts = [parts[0] + 1, 0, 0]
69+
elif bump == "minor": parts = [parts[0], parts[1] + 1, 0]
70+
else: parts = [parts[0], parts[1], parts[2] + 1]
71+
new_ver = ".".join(str(x) for x in parts)
72+
open("pyproject.toml", "w").write(
73+
re.sub(r'^version = ".+?"', f'version = "{new_ver}"', pp, count=1, flags=re.M)
74+
)
75+
open("src/roxy_sdk/version.py", "w").write(f'VERSION = "{new_ver}"\n')
76+
open("/tmp/new_version.txt", "w").write(new_ver)
77+
print(f"Bumped {ver} -> {new_ver} ({bump})")
78+
PY
7679
7780
- name: Build
7881
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
79-
run: hatch build
82+
run: uv build
8083

8184
- name: Publish to PyPI
8285
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
@@ -88,7 +91,7 @@ jobs:
8891
git config user.name "github-actions[bot]"
8992
git config user.email "github-actions[bot]@users.noreply.github.com"
9093
VERSION=$(cat /tmp/new_version.txt)
91-
git add src/roxy_sdk/version.py specs/openapi.json src/roxy_sdk/factory.py
94+
git add pyproject.toml src/roxy_sdk/version.py specs/openapi.json src/roxy_sdk/factory.py
9295
git commit -m "release: v$VERSION"
9396
git tag "v$VERSION"
9497
git push --follow-tags

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ build/
2828
.ruff_cache/
2929
*.so
3030

31-
# Hatch
32-
.hatch/
31+
# uv
32+
# uv.lock is committed for reproducibility
3333

3434
# Editor
3535
.DS_Store

AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# roxy-sdk (Python) Agent Guide
22

3-
Python SDK for RoxyAPI. Multi-domain spiritual and metaphysical intelligence API. One API key, 10 domains, sync and async support.
3+
Python SDK for RoxyAPI. Multi-domain spiritual and metaphysical intelligence API. One API key, 11 domains, sync and async support.
44

55
## Install and initialize
66

@@ -30,6 +30,7 @@ Type `roxy.` to see all available namespaces:
3030
| `roxy.iching` | I Ching: hexagrams, trigrams, coin casting, daily readings |
3131
| `roxy.angel_numbers` | Angel number meanings, pattern analysis, daily guidance |
3232
| `roxy.dreams` | Dream symbol dictionary and interpretations |
33+
| `roxy.biorhythm` | Physical, emotional, intellectual cycles, forecasts, compatibility |
3334
| `roxy.location` | City geocoding for birth chart coordinates |
3435
| `roxy.usage` | API usage stats and subscription info |
3536

@@ -116,6 +117,8 @@ Error codes: `validation_error`, `api_key_required`, `invalid_api_key`, `subscri
116117
| I Ching reading | `roxy.iching.cast_reading()` |
117118
| Angel number meaning | `roxy.angel_numbers.get_angel_number(number="1111")` |
118119
| Dream symbol lookup | `roxy.dreams.get_dream_symbol(id="flying")` |
120+
| Daily biorhythm | `roxy.biorhythm.get_daily_biorhythm(date="1990-01-15")` |
121+
| Biorhythm forecast | `roxy.biorhythm.get_biorhythm_forecast(date="1990-01-15", days=30)` |
119122
| Find city coordinates | `roxy.location.search_cities(q="Mumbai")` |
120123
| Check API usage | `roxy.usage.get_usage_stats()` |
121124

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![API Reference](https://img.shields.io/badge/api%20reference-roxyapi.com-blue)](https://roxyapi.com/api-reference)
77
[![License](https://img.shields.io/github/license/RoxyAPI/sdk-python)](https://github.com/RoxyAPI/sdk-python/blob/main/LICENSE)
88

9-
Python SDK for [RoxyAPI](https://roxyapi.com). Astrology, tarot, numerology, I Ching, crystals, angel numbers, dream interpretation, and more. One API key, 10 domains, 120+ endpoints.
9+
Python SDK for [RoxyAPI](https://roxyapi.com). Astrology, tarot, numerology, I Ching, crystals, angel numbers, dream interpretation, biorhythm, and more. One API key, 11 domains, 120+ endpoints.
1010

1111
## Install
1212

@@ -88,6 +88,7 @@ print(f"I Ching: {reading}")
8888
| Crystals | `roxy.crystals` | Healing properties, zodiac/chakra pairings, birthstones, search |
8989
| Angel Numbers | `roxy.angel_numbers` | Number meanings, pattern analysis, daily guidance |
9090
| Dreams | `roxy.dreams` | Symbol dictionary, interpretations, daily guidance |
91+
| Biorhythm | `roxy.biorhythm` | Physical, emotional, intellectual cycles, forecasts, compatibility |
9192
| Location | `roxy.location` | City geocoding for birth chart coordinates |
9293
| Usage | `roxy.usage` | API usage stats and subscription info |
9394

lefthook.yml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
pre-commit:
2+
parallel: true
23
commands:
4+
ruff-format:
5+
glob: "*.py"
6+
run: uv run ruff format {staged_files}
7+
stage_fixed: true
38
ruff-check:
49
glob: "*.py"
5-
run: ruff check --fix . && ruff format .
10+
run: uv run ruff check --fix {staged_files}
611
stage_fixed: true
7-
typecheck:
8-
run: mypy src/roxy_sdk/factory.py src/roxy_sdk/__init__.py
912

1013
pre-push:
14+
parallel: true
1115
commands:
12-
ruff-full:
13-
run: ruff check .
14-
typecheck:
15-
run: mypy src/roxy_sdk/factory.py src/roxy_sdk/__init__.py
16-
test:
17-
run: python -m pytest tests/test_factory.py -q
16+
ruff-check-strict:
17+
run: uv run ruff check .
18+
type-check:
19+
run: uv run mypy src/roxy_sdk/__init__.py
20+
pytest:
21+
run: uv run pytest tests/test_factory.py -q

pyproject.toml

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
[build-system]
2-
requires = ["hatchling"]
3-
build-backend = "hatchling.build"
2+
requires = ["uv_build>=0.11.6,<0.12"]
3+
build-backend = "uv_build"
44

55
[project]
66
name = "roxy-sdk"
7-
dynamic = ["version"]
7+
version = "0.1.0"
88
description = "Python SDK for RoxyAPI. Astrology, tarot, numerology, and more."
99
readme = "README.md"
10-
license = { text = "MIT" }
10+
license = "MIT"
11+
license-files = ["LICENSE"]
1112
requires-python = ">=3.10"
1213
dependencies = [
1314
"httpx>=0.27.0",
@@ -17,9 +18,8 @@ authors = [
1718
]
1819
keywords = ["astrology", "tarot", "numerology", "api", "sdk", "vedic", "horoscope"]
1920
classifiers = [
20-
"Development Status :: 3 - Alpha",
21+
"Development Status :: 4 - Beta",
2122
"Intended Audience :: Developers",
22-
"License :: OSI Approved :: MIT License",
2323
"Programming Language :: Python :: 3",
2424
"Programming Language :: Python :: 3.10",
2525
"Programming Language :: Python :: 3.11",
@@ -30,35 +30,22 @@ classifiers = [
3030

3131
[project.urls]
3232
Homepage = "https://roxyapi.com"
33-
Repository = "https://github.com/roxyapi/sdk-python"
33+
Repository = "https://github.com/RoxyAPI/sdk-python"
3434
Documentation = "https://roxyapi.com/docs"
3535

36-
[tool.hatch.version]
37-
path = "src/roxy_sdk/version.py"
38-
pattern = 'VERSION = "(?P<version>[^"]+)"'
36+
[tool.uv.build-backend]
37+
module-name = "roxy_sdk"
38+
module-root = "src"
39+
source-exclude = ["**/_generated/**", "**/__pycache__/**"]
3940

40-
[tool.hatch.build.targets.wheel]
41-
packages = ["src/roxy_sdk"]
42-
exclude = ["src/roxy_sdk/_generated"]
43-
44-
[tool.hatch.build.targets.sdist]
45-
include = ["src/roxy_sdk", "AGENTS.md", "README.md", "LICENSE"]
46-
47-
[tool.hatch.envs.default]
48-
dependencies = [
41+
[dependency-groups]
42+
dev = [
4943
"pytest>=8.0",
5044
"pytest-asyncio>=0.23",
5145
"mypy>=1.9",
5246
"ruff>=0.4",
5347
]
5448

55-
[tool.hatch.envs.default.scripts]
56-
test = "pytest tests/"
57-
typecheck = "mypy src/roxy_sdk/factory.py src/roxy_sdk/__init__.py"
58-
check = "ruff check --fix . && ruff format ."
59-
lint = "ruff check ."
60-
build = "hatch build"
61-
6249
[tool.ruff]
6350
line-length = 100
6451
target-version = "py310"

src/roxy_sdk/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = "0.0.1"
1+
VERSION = "0.1.0"

0 commit comments

Comments
 (0)