Skip to content

Commit 1121657

Browse files
committed
feat: implement ATH Móvil Python SDK with full API support
Add complete implementation of athm Python library for ATH Móvil Payment Button API: Core Features: - Type-safe synchronous client with Pydantic validation - Complete payment lifecycle (create, find, authorize, cancel, refund) - Intelligent error handling with hierarchical exceptions - Automatic retry logic with exponential backoff - Context manager support for resource cleanup Implementation: - Client with internal auth token management - Request/response models with strict validation - Comprehensive exception hierarchy with error code classification - Utility functions for amount formatting, phone validation - Business rule enforcement (amounts, timeouts, field lengths) Testing & Quality: - 123 unit tests with 95%+ coverage - Full test suite for all components - Type checking with strict mypy configuration - Linting with ruff, security checks with bandit - Pre-commit hooks for code quality Documentation: - Complete MkDocs documentation site - API reference with examples - Error handling guide - Advanced usage patterns CI/CD: - GitHub Actions workflows for test, lint, type-check - Automated release process with commitizen - Documentation deployment to Read the Docs Development Setup: - uv for dependency management - Pre-commit hooks for quality checks - Conventional commits with commitizen
1 parent 8a60d9a commit 1121657

39 files changed

+8437
-5
lines changed

.czrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"commitizen": {
3+
"name": "cz_conventional_commits",
4+
"version": "0.1.0",
5+
"version_files": [
6+
"athm/__init__.py:__version__",
7+
"pyproject.toml:version"
8+
],
9+
"tag_format": "v$version",
10+
"update_changelog_on_bump": true,
11+
"changelog_file": "CHANGELOG.md"
12+
}
13+
}

.github/workflows/docs.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
jobs:
16+
build-docs:
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Install uv
23+
uses: astral-sh/setup-uv@v3
24+
with:
25+
enable-cache: true
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: "3.11"
31+
32+
- name: Install dependencies
33+
run: |
34+
uv sync --all-extras --dev
35+
uv pip install -e .
36+
37+
- name: Build MkDocs documentation
38+
run: |
39+
uv run mkdocs build
40+
41+
- name: Upload documentation artifacts
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: docs
45+
path: site/
46+
47+
deploy-docs:
48+
needs: build-docs
49+
runs-on: ubuntu-latest
50+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
51+
environment:
52+
name: github-pages
53+
url: ${{ steps.deployment.outputs.page_url }}
54+
55+
steps:
56+
- uses: actions/download-artifact@v4
57+
with:
58+
name: docs
59+
path: site/
60+
61+
- name: Setup Pages
62+
uses: actions/configure-pages@v5
63+
64+
- name: Upload to GitHub Pages
65+
uses: actions/upload-pages-artifact@v4
66+
with:
67+
path: site/
68+
69+
- name: Deploy to GitHub Pages
70+
id: deployment
71+
uses: actions/deploy-pages@v4

.github/workflows/lint.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
workflow_dispatch:
9+
10+
jobs:
11+
lint:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Install uv
18+
uses: astral-sh/setup-uv@v3
19+
with:
20+
enable-cache: true
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: "3.11"
26+
27+
- name: Install dependencies
28+
run: |
29+
uv sync --all-extras --dev
30+
uv pip install -e .
31+
32+
- name: Run Ruff linter
33+
run: |
34+
uv run ruff check athm tests
35+
36+
- name: Run Ruff formatter
37+
run: |
38+
uv run ruff format --check athm tests

.github/workflows/release.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
inputs:
9+
version:
10+
description: "Version to release (e.g., 0.1.0)"
11+
required: true
12+
13+
permissions:
14+
contents: write
15+
id-token: write
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0 # For changelog generation
25+
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v3
28+
29+
- name: Set up Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: "3.11"
33+
34+
- name: Install dependencies
35+
run: |
36+
uv sync --all-extras --dev
37+
uv pip install build twine
38+
39+
- name: Run tests
40+
run: |
41+
uv run pytest tests/ -v
42+
43+
- name: Build package
44+
run: |
45+
uv run python -m build
46+
47+
- name: Check package
48+
run: |
49+
uv run twine check dist/*
50+
51+
- name: Upload build artifacts
52+
uses: actions/upload-artifact@v4
53+
with:
54+
name: dist
55+
path: dist/
56+
57+
publish-test:
58+
needs: build
59+
runs-on: ubuntu-latest
60+
if: github.event_name == 'workflow_dispatch'
61+
environment:
62+
name: test-pypi
63+
url: https://test.pypi.org/p/athm
64+
65+
steps:
66+
- uses: actions/download-artifact@v4
67+
with:
68+
name: dist
69+
path: dist/
70+
71+
- name: Publish to TestPyPI
72+
uses: pypa/gh-action-pypi-publish@release/v1
73+
with:
74+
repository-url: https://test.pypi.org/legacy/
75+
skip-existing: true
76+
77+
publish:
78+
needs: build
79+
runs-on: ubuntu-latest
80+
if: startsWith(github.ref, 'refs/tags/')
81+
environment:
82+
name: pypi
83+
url: https://pypi.org/p/athm
84+
85+
steps:
86+
- uses: actions/checkout@v4
87+
with:
88+
fetch-depth: 0
89+
90+
- uses: actions/download-artifact@v4
91+
with:
92+
name: dist
93+
path: dist/
94+
95+
- name: Generate changelog
96+
run: |
97+
pip install git-cliff
98+
git cliff -o RELEASE_NOTES.md --latest
99+
100+
- name: Create GitHub Release
101+
uses: softprops/action-gh-release@v1
102+
with:
103+
body_path: RELEASE_NOTES.md
104+
files: dist/*
105+
fail_on_unmatched_files: true
106+
draft: false
107+
prerelease: ${{ contains(github.ref, 'rc') || contains(github.ref, 'alpha') || contains(github.ref, 'beta') }}
108+
109+
- name: Publish to PyPI
110+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/test.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os: [ubuntu-latest, macos-latest, windows-latest]
17+
python-version: ["3.10", "3.11", "3.12", "3.13"]
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Install uv
23+
uses: astral-sh/setup-uv@v3
24+
with:
25+
enable-cache: true
26+
cache-dependency-glob: "uv.lock"
27+
28+
- name: Set up Python ${{ matrix.python-version }}
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: ${{ matrix.python-version }}
32+
33+
- name: Install dependencies
34+
run: |
35+
uv sync --all-extras --dev
36+
uv pip install -e .
37+
38+
- name: Run tests with coverage
39+
run: |
40+
uv run pytest tests/ -v --cov=athm --cov-report=term-missing --cov-report=xml --cov-report=html
41+
42+
- name: Upload coverage reports
43+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
44+
uses: codecov/codecov-action@v5
45+
with:
46+
file: ./coverage.xml
47+
flags: unittests
48+
name: codecov-umbrella
49+
fail_ci_if_error: false
50+
51+
- name: Upload coverage HTML report
52+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: coverage-report
56+
path: htmlcov/
57+
58+
- name: Check coverage threshold
59+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
60+
run: |
61+
uv run python -c "
62+
import xml.etree.ElementTree as ET
63+
tree = ET.parse('coverage.xml')
64+
root = tree.getroot()
65+
coverage = float(root.attrib['line-rate']) * 100
66+
print(f'Coverage: {coverage:.2f}%')
67+
if coverage < 100:
68+
print(f'Coverage {coverage:.2f}% is below required 100%')
69+
exit(1)
70+
"

.github/workflows/type-check.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Type Check
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
workflow_dispatch:
9+
10+
jobs:
11+
type-check:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Install uv
18+
uses: astral-sh/setup-uv@v3
19+
with:
20+
enable-cache: true
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: "3.11"
26+
27+
- name: Install dependencies
28+
run: |
29+
uv sync --all-extras --dev
30+
uv pip install -e .
31+
32+
- name: Run mypy type checker
33+
run: |
34+
uv run mypy athm
35+
36+
- name: Verify py.typed marker
37+
run: |
38+
if [ ! -f "athm/py.typed" ]; then
39+
echo "py.typed marker file is missing"
40+
exit 1
41+
fi

.gitignore

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ ipython_config.py
9898
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
9999
# This is especially recommended for binary packages to ensure reproducibility, and is more
100100
# commonly ignored for libraries.
101-
#uv.lock
101+
.uv/
102102

103103
# poetry
104104
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
@@ -182,9 +182,9 @@ cython_debug/
182182
.abstra/
183183

184184
# Visual Studio Code
185-
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
185+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186186
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187-
# and can be added to the global gitignore or merged into this file. However, if you prefer,
187+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
188188
# you could uncomment the following to ignore the entire vscode folder
189189
# .vscode/
190190

@@ -205,3 +205,10 @@ cython_debug/
205205
marimo/_static/
206206
marimo/_lsp/
207207
__marimo__/
208+
209+
210+
# Developer tools
211+
.devcontainer/
212+
.devcontainers/
213+
.vscode/
214+
.claude/

0 commit comments

Comments
 (0)