leapocr 0.0.1__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.
Files changed (142) hide show
  1. leapocr-0.0.1/.github/PULL_REQUEST_TEMPLATE.md +54 -0
  2. leapocr-0.0.1/.github/PYPI_SETUP.md +134 -0
  3. leapocr-0.0.1/.github/workflows/ci.yml +130 -0
  4. leapocr-0.0.1/.github/workflows/integration-tests.yml +50 -0
  5. leapocr-0.0.1/.github/workflows/release.yml +123 -0
  6. leapocr-0.0.1/.gitignore +216 -0
  7. leapocr-0.0.1/.python-version +1 -0
  8. leapocr-0.0.1/CHANGELOG.md +57 -0
  9. leapocr-0.0.1/CONTRIBUTING.md +376 -0
  10. leapocr-0.0.1/IMPLEMENTATION_SUMMARY.md +362 -0
  11. leapocr-0.0.1/Makefile +158 -0
  12. leapocr-0.0.1/PKG-INFO +577 -0
  13. leapocr-0.0.1/QUICKSTART.md +276 -0
  14. leapocr-0.0.1/README.md +545 -0
  15. leapocr-0.0.1/RELEASING.md +191 -0
  16. leapocr-0.0.1/SDK_IMPLEMENTATION_PLAN.md +1890 -0
  17. leapocr-0.0.1/examples/README.md +234 -0
  18. leapocr-0.0.1/examples/advanced/batch_processing.py +102 -0
  19. leapocr-0.0.1/examples/advanced/custom_config.py +116 -0
  20. leapocr-0.0.1/examples/advanced/schema_extraction.py +164 -0
  21. leapocr-0.0.1/examples/basic/process_file.py +72 -0
  22. leapocr-0.0.1/examples/basic/process_url.py +91 -0
  23. leapocr-0.0.1/examples/error_handling/error_types.py +201 -0
  24. leapocr-0.0.1/examples/error_handling/timeout_handling.py +172 -0
  25. leapocr-0.0.1/leapocr/__init__.py +91 -0
  26. leapocr-0.0.1/leapocr/_internal/__init__.py +1 -0
  27. leapocr-0.0.1/leapocr/_internal/polling.py +130 -0
  28. leapocr-0.0.1/leapocr/_internal/retry.py +101 -0
  29. leapocr-0.0.1/leapocr/_internal/upload.py +118 -0
  30. leapocr-0.0.1/leapocr/_internal/utils.py +51 -0
  31. leapocr-0.0.1/leapocr/_internal/validation.py +172 -0
  32. leapocr-0.0.1/leapocr/client.py +96 -0
  33. leapocr-0.0.1/leapocr/config.py +59 -0
  34. leapocr-0.0.1/leapocr/errors.py +155 -0
  35. leapocr-0.0.1/leapocr/generated/.openapi-generator/FILES +89 -0
  36. leapocr-0.0.1/leapocr/generated/.openapi-generator/VERSION +1 -0
  37. leapocr-0.0.1/leapocr/generated/.openapi-generator-ignore +23 -0
  38. leapocr-0.0.1/leapocr/generated/leapocr/__init__.py +0 -0
  39. leapocr-0.0.1/leapocr/generated/leapocr/generated/__init__.py +202 -0
  40. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/__init__.py +15 -0
  41. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/analytics_api.py +868 -0
  42. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/authentication_api.py +172 -0
  43. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/credits_api.py +653 -0
  44. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/health_api.py +161 -0
  45. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/jobs_api.py +836 -0
  46. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/models_api.py +161 -0
  47. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/ocr_api.py +863 -0
  48. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/sdk_api.py +744 -0
  49. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/templates_api.py +1006 -0
  50. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/upload_api.py +465 -0
  51. leapocr-0.0.1/leapocr/generated/leapocr/generated/api/webhooks_api.py +324 -0
  52. leapocr-0.0.1/leapocr/generated/leapocr/generated/api_client.py +738 -0
  53. leapocr-0.0.1/leapocr/generated/leapocr/generated/api_response.py +25 -0
  54. leapocr-0.0.1/leapocr/generated/leapocr/generated/configuration.py +476 -0
  55. leapocr-0.0.1/leapocr/generated/leapocr/generated/exceptions.py +167 -0
  56. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/__init__.py +84 -0
  57. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_credits_overview.py +82 -0
  58. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_credits_timeseries_point.py +82 -0
  59. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_credits_usage_response.py +102 -0
  60. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_job_overview.py +94 -0
  61. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_job_timeseries_point.py +88 -0
  62. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_jobs_timeseries_get200_response.py +86 -0
  63. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_model_usage_stat.py +78 -0
  64. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_overview_response.py +100 -0
  65. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_page_overview.py +82 -0
  66. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_page_timeseries_point.py +84 -0
  67. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_pages_timeseries_get200_response.py +86 -0
  68. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_range.py +80 -0
  69. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_template_stat.py +82 -0
  70. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_top_templates_response.py +86 -0
  71. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/analytics_webhook_summary.py +82 -0
  72. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/auth_auth_response.py +81 -0
  73. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_active_meter_response.py +82 -0
  74. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_active_subscription_response.py +88 -0
  75. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_catalog_benefit.py +74 -0
  76. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_catalog_price.py +76 -0
  77. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_catalog_product.py +96 -0
  78. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_credit_balance_response.py +120 -0
  79. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_credit_transaction_organization_response.py +102 -0
  80. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_credit_transaction_project_response.py +102 -0
  81. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_credit_transactions_response_credits_credit_transaction_organization_response.py +86 -0
  82. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_credit_transactions_response_credits_credit_transaction_project_response.py +86 -0
  83. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_granted_benefit_response.py +82 -0
  84. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_pagination_info.py +76 -0
  85. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/credits_product_catalog.py +89 -0
  86. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/health_health_check.py +78 -0
  87. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/health_health_status.py +97 -0
  88. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/health_health_summary.py +78 -0
  89. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_job_list_item.py +100 -0
  90. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_job_management_response.py +82 -0
  91. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_job_response.py +102 -0
  92. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_job_status_response.py +90 -0
  93. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_jobs_list_response.py +86 -0
  94. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_pagination_info.py +78 -0
  95. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_restart_job_request.py +74 -0
  96. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_retry_job_request.py +74 -0
  97. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_workflow_job_status_info.py +80 -0
  98. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_workflow_progress_info.py +80 -0
  99. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/jobs_workflow_status_info.py +104 -0
  100. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_list_model_response.py +80 -0
  101. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_list_models_list_response.py +82 -0
  102. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_ocr_result_response.py +106 -0
  103. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_ocr_status_response.py +84 -0
  104. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_page_metadata.py +76 -0
  105. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_page_response.py +84 -0
  106. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/models_pagination_response.py +78 -0
  107. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/response_error_message.py +72 -0
  108. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/response_error_response.py +85 -0
  109. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/status_response.py +88 -0
  110. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/templates_create_template_request.py +90 -0
  111. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/templates_list_templates_response.py +88 -0
  112. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/templates_template_response.py +104 -0
  113. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/templates_template_stats_response.py +88 -0
  114. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/templates_update_template_request.py +88 -0
  115. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_completed_part.py +74 -0
  116. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_direct_upload_complete_request.py +80 -0
  117. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_direct_upload_complete_response.py +78 -0
  118. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_direct_upload_response.py +94 -0
  119. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_initiate_direct_upload_request.py +96 -0
  120. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_multipart_part.py +78 -0
  121. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_remote_url_upload_request.py +94 -0
  122. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/upload_remote_url_upload_response.py +78 -0
  123. leapocr-0.0.1/leapocr/generated/leapocr/generated/models/webhooks_r2_upload_notification.py +76 -0
  124. leapocr-0.0.1/leapocr/generated/leapocr/generated/rest.py +257 -0
  125. leapocr-0.0.1/leapocr/generated/leapocr/generated_README.md +205 -0
  126. leapocr-0.0.1/leapocr/models.py +157 -0
  127. leapocr-0.0.1/leapocr/ocr.py +376 -0
  128. leapocr-0.0.1/openapi-sdk.json +979 -0
  129. leapocr-0.0.1/openapi.json +22 -0
  130. leapocr-0.0.1/openapitools.json +7 -0
  131. leapocr-0.0.1/pyproject.toml +119 -0
  132. leapocr-0.0.1/pytest.ini +46 -0
  133. leapocr-0.0.1/scripts/filter_sdk_endpoints.py +189 -0
  134. leapocr-0.0.1/tests/__init__.py +1 -0
  135. leapocr-0.0.1/tests/integration/__init__.py +1 -0
  136. leapocr-0.0.1/tests/integration/test_ocr.py +322 -0
  137. leapocr-0.0.1/tests/unit/__init__.py +1 -0
  138. leapocr-0.0.1/tests/unit/test_errors.py +233 -0
  139. leapocr-0.0.1/tests/unit/test_models.py +356 -0
  140. leapocr-0.0.1/tests/unit/test_utils.py +136 -0
  141. leapocr-0.0.1/tests/unit/test_validation.py +178 -0
  142. leapocr-0.0.1/uv.lock +673 -0
@@ -0,0 +1,54 @@
1
+ ## Description
2
+
3
+ <!-- Provide a brief description of your changes -->
4
+
5
+ ## Type of Change
6
+
7
+ <!-- Mark the relevant option with an "x" -->
8
+
9
+ - [ ] Bug fix (non-breaking change which fixes an issue)
10
+ - [ ] New feature (non-breaking change which adds functionality)
11
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
12
+ - [ ] Documentation update
13
+ - [ ] Performance improvement
14
+ - [ ] Code refactoring
15
+ - [ ] Test improvements
16
+
17
+ ## Related Issues
18
+
19
+ <!-- Link any related issues here -->
20
+
21
+ Closes #
22
+
23
+ ## Changes Made
24
+
25
+ <!-- List the specific changes made in this PR -->
26
+
27
+ -
28
+ -
29
+ -
30
+
31
+ ## Testing
32
+
33
+ <!-- Describe the tests you ran to verify your changes -->
34
+
35
+ - [ ] Unit tests pass (`make test`)
36
+ - [ ] Integration tests pass (if applicable)
37
+ - [ ] Added new tests for new functionality
38
+ - [ ] All existing tests still pass
39
+
40
+ ## Code Quality
41
+
42
+ <!-- Confirm you've met these requirements -->
43
+
44
+ - [ ] Code follows the project's style guidelines
45
+ - [ ] Ran `make format` to format code
46
+ - [ ] Ran `make lint` and fixed all issues
47
+ - [ ] Ran `make type-check` and fixed all type errors
48
+ - [ ] Added docstrings for new functions/classes
49
+ - [ ] Updated documentation (if needed)
50
+ - [ ] Updated CHANGELOG.md (if applicable)
51
+
52
+ ## Additional Context
53
+
54
+ <!-- Add any other context about the PR here -->
@@ -0,0 +1,134 @@
1
+ # PyPI Trusted Publishing Setup
2
+
3
+ This project uses PyPI's trusted publishing feature to securely publish releases without needing API tokens.
4
+
5
+ ## Initial Setup (One-Time)
6
+
7
+ ### 1. Register the Package on PyPI (if not already registered)
8
+
9
+ If this is the first release:
10
+
11
+ 1. Build the package locally:
12
+ ```bash
13
+ uv build
14
+ ```
15
+
16
+ 2. Manually upload the first version using an API token:
17
+ ```bash
18
+ # Create a PyPI API token at: https://pypi.org/manage/account/token/
19
+ uv run twine upload dist/*
20
+ ```
21
+
22
+ ### 2. Configure Trusted Publishing
23
+
24
+ 1. Go to https://pypi.org/manage/project/leapocr/settings/publishing/
25
+
26
+ 2. Scroll to "Publishing" section
27
+
28
+ 3. Click "Add a new pending publisher"
29
+
30
+ 4. Fill in the form:
31
+ - **PyPI Project Name**: `leapocr`
32
+ - **Owner**: `leapocr` (GitHub organization/user)
33
+ - **Repository name**: `leapocr-python`
34
+ - **Workflow name**: `release.yml`
35
+ - **Environment name**: `pypi`
36
+
37
+ 5. Click "Add"
38
+
39
+ ### 3. Create PyPI Environment in GitHub
40
+
41
+ 1. Go to https://github.com/leapocr/leapocr-python/settings/environments
42
+
43
+ 2. Click "New environment"
44
+
45
+ 3. Name it `pypi`
46
+
47
+ 4. (Optional) Add protection rules:
48
+ - Required reviewers (for manual approval before publish)
49
+ - Deployment branches (limit to `main` branch only)
50
+
51
+ 5. Click "Configure environment"
52
+
53
+ ## How It Works
54
+
55
+ 1. When you push a tag like `v0.1.0`:
56
+ ```bash
57
+ git tag -a v0.1.0 -m "Release v0.1.0"
58
+ git push origin v0.1.0
59
+ ```
60
+
61
+ 2. GitHub Actions workflow triggers (`release.yml`)
62
+
63
+ 3. The workflow:
64
+ - Builds the package
65
+ - Requests a short-lived token from PyPI via OIDC
66
+ - Uses that token to publish to PyPI
67
+ - Creates a GitHub release
68
+
69
+ 4. No API tokens needed! ✨
70
+
71
+ ## Security Benefits
72
+
73
+ - **No long-lived tokens**: Tokens are generated per-release
74
+ - **Scoped access**: Token only works for this specific project
75
+ - **Audit trail**: All releases tracked in GitHub Actions
76
+ - **Revocable**: Can be disabled/reconfigured at any time
77
+
78
+ ## Troubleshooting
79
+
80
+ ### Error: "Trusted publisher configuration does not match"
81
+
82
+ This usually means:
83
+ - The repository name is wrong
84
+ - The workflow name doesn't match (`release.yml`)
85
+ - The environment name doesn't match (`pypi`)
86
+ - The tag trigger isn't configured correctly
87
+
88
+ **Solution**: Double-check the PyPI publisher settings match your GitHub repository exactly.
89
+
90
+ ### Error: "Insufficient permissions"
91
+
92
+ The workflow needs `id-token: write` permission:
93
+
94
+ ```yaml
95
+ permissions:
96
+ contents: read
97
+ id-token: write # Required for trusted publishing
98
+ ```
99
+
100
+ This is already configured in `release.yml`.
101
+
102
+ ### Error: "Package already exists"
103
+
104
+ If you're trying to upload a version that already exists on PyPI:
105
+
106
+ 1. Bump the version in `pyproject.toml`
107
+ 2. Create a new tag with the new version
108
+ 3. Delete the old tag if needed:
109
+ ```bash
110
+ git tag -d v0.1.0
111
+ git push origin :refs/tags/v0.1.0
112
+ ```
113
+
114
+ ## Testing Releases
115
+
116
+ To test the release process without publishing to PyPI:
117
+
118
+ 1. Use TestPyPI for testing:
119
+ - Configure a separate trusted publisher on TestPyPI
120
+ - Create a test workflow that publishes to TestPyPI
121
+ - Test with: `pip install -i https://test.pypi.org/simple/ leapocr`
122
+
123
+ 2. Or run the build locally:
124
+ ```bash
125
+ make build
126
+ # Check the dist/ folder
127
+ ls -lh dist/
128
+ ```
129
+
130
+ ## References
131
+
132
+ - [PyPI Trusted Publishing Guide](https://docs.pypi.org/trusted-publishers/)
133
+ - [GitHub Actions OIDC](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
134
+ - [PyPA gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish)
@@ -0,0 +1,130 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, new]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint and Format Check
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: '3.12'
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v3
24
+ with:
25
+ enable-cache: true
26
+
27
+ - name: Install dependencies
28
+ run: uv sync
29
+
30
+ - name: Run ruff format check
31
+ run: uv run ruff format --check .
32
+
33
+ - name: Run ruff lint
34
+ run: uv run ruff check .
35
+
36
+ type-check:
37
+ name: Type Check
38
+ runs-on: ubuntu-latest
39
+
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+
43
+ - name: Set up Python
44
+ uses: actions/setup-python@v5
45
+ with:
46
+ python-version: '3.12'
47
+
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@v3
50
+ with:
51
+ enable-cache: true
52
+
53
+ - name: Install dependencies
54
+ run: uv sync
55
+
56
+ - name: Run mypy
57
+ run: uv run mypy leapocr/
58
+
59
+ test:
60
+ name: Test Python ${{ matrix.python-version }}
61
+ runs-on: ubuntu-latest
62
+ strategy:
63
+ fail-fast: false
64
+ matrix:
65
+ python-version: ['3.9', '3.10', '3.11', '3.12']
66
+
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+
70
+ - name: Set up Python ${{ matrix.python-version }}
71
+ uses: actions/setup-python@v5
72
+ with:
73
+ python-version: ${{ matrix.python-version }}
74
+
75
+ - name: Install uv
76
+ uses: astral-sh/setup-uv@v3
77
+ with:
78
+ enable-cache: true
79
+
80
+ - name: Install dependencies
81
+ run: uv sync
82
+
83
+ - name: Run unit tests
84
+ run: uv run pytest tests/unit/ -v --tb=short
85
+
86
+ - name: Run tests with coverage
87
+ if: matrix.python-version == '3.12'
88
+ run: |
89
+ uv run pytest tests/unit/ --cov=leapocr --cov-report=xml --cov-report=term
90
+
91
+ - name: Upload coverage to Codecov
92
+ if: matrix.python-version == '3.12'
93
+ uses: codecov/codecov-action@v4
94
+ with:
95
+ file: ./coverage.xml
96
+ fail_ci_if_error: false
97
+
98
+ build:
99
+ name: Build Distribution
100
+ runs-on: ubuntu-latest
101
+ needs: [lint, type-check, test]
102
+
103
+ steps:
104
+ - uses: actions/checkout@v4
105
+
106
+ - name: Set up Python
107
+ uses: actions/setup-python@v5
108
+ with:
109
+ python-version: '3.12'
110
+
111
+ - name: Install uv
112
+ uses: astral-sh/setup-uv@v3
113
+ with:
114
+ enable-cache: true
115
+
116
+ - name: Build package
117
+ run: uv build
118
+
119
+ - name: Verify build artifacts
120
+ run: |
121
+ ls -lh dist/
122
+ python -m pip install dist/*.whl
123
+ python -c "import leapocr; print(f'Installed version: {leapocr.__version__}')"
124
+
125
+ - name: Upload build artifacts
126
+ uses: actions/upload-artifact@v4
127
+ with:
128
+ name: dist
129
+ path: dist/
130
+ retention-days: 30
@@ -0,0 +1,50 @@
1
+ name: Integration Tests
2
+
3
+ on:
4
+ workflow_dispatch: # Manual trigger only
5
+ inputs:
6
+ api_base_url:
7
+ description: 'API Base URL'
8
+ required: false
9
+ default: 'http://localhost:8080/api/v1'
10
+ schedule:
11
+ - cron: '0 0 * * 0' # Weekly on Sunday at midnight
12
+
13
+ jobs:
14
+ integration-test:
15
+ name: Integration Tests
16
+ runs-on: ubuntu-latest
17
+ environment: integration-testing
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: '3.12'
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v3
29
+ with:
30
+ enable-cache: true
31
+
32
+ - name: Install dependencies
33
+ run: uv sync
34
+
35
+ - name: Run integration tests
36
+ env:
37
+ LEAPOCR_API_KEY: ${{ secrets.LEAPOCR_API_KEY }}
38
+ OCR_BASE_URL: ${{ github.event.inputs.api_base_url || 'http://localhost:8080/api/v1' }}
39
+ run: |
40
+ uv run pytest tests/integration/ -v --tb=short -m integration
41
+
42
+ - name: Upload test results
43
+ if: always()
44
+ uses: actions/upload-artifact@v4
45
+ with:
46
+ name: integration-test-results
47
+ path: |
48
+ pytest-report.xml
49
+ pytest-coverage.xml
50
+ retention-days: 30
@@ -0,0 +1,123 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write # Required for trusted publishing to PyPI
11
+
12
+ jobs:
13
+ build:
14
+ name: Build distribution
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.12'
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v3
27
+ with:
28
+ enable-cache: true
29
+
30
+ - name: Verify version matches tag
31
+ run: |
32
+ TAG=${GITHUB_REF#refs/tags/v}
33
+ VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
34
+ if [ "$TAG" != "$VERSION" ]; then
35
+ echo "Error: Tag version ($TAG) does not match package version ($VERSION)"
36
+ exit 1
37
+ fi
38
+ echo "Version check passed: $VERSION"
39
+
40
+ - name: Build package
41
+ run: uv build
42
+
43
+ - name: Verify build artifacts
44
+ run: |
45
+ ls -lh dist/
46
+ echo "Build artifacts:"
47
+ echo "$(ls dist/)"
48
+
49
+ - name: Upload artifacts
50
+ uses: actions/upload-artifact@v4
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+ retention-days: 7
55
+
56
+ publish:
57
+ name: Publish to PyPI
58
+ needs: build
59
+ runs-on: ubuntu-latest
60
+ environment:
61
+ name: pypi
62
+ url: https://pypi.org/project/leapocr/
63
+
64
+ steps:
65
+ - name: Download artifacts
66
+ uses: actions/download-artifact@v4
67
+ with:
68
+ name: dist
69
+ path: dist/
70
+
71
+ - name: Publish to PyPI
72
+ uses: pypa/gh-action-pypi-publish@release/v1
73
+ with:
74
+ print-hash: true
75
+
76
+ create-release:
77
+ name: Create GitHub Release
78
+ needs: publish
79
+ runs-on: ubuntu-latest
80
+ permissions:
81
+ contents: write
82
+
83
+ steps:
84
+ - uses: actions/checkout@v4
85
+
86
+ - name: Extract release notes
87
+ id: extract-notes
88
+ run: |
89
+ VERSION=${GITHUB_REF#refs/tags/v}
90
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
91
+
92
+ - name: Create GitHub Release
93
+ uses: softprops/action-gh-release@v2
94
+ with:
95
+ name: Release v${{ steps.extract-notes.outputs.version }}
96
+ body: |
97
+ ## Installation
98
+
99
+ ```bash
100
+ pip install leapocr==${{ steps.extract-notes.outputs.version }}
101
+ ```
102
+
103
+ Or using uv:
104
+
105
+ ```bash
106
+ uv add leapocr==${{ steps.extract-notes.outputs.version }}
107
+ ```
108
+
109
+ ## What's Changed
110
+
111
+ See the [changelog](https://github.com/leapocr/leapocr-python/blob/main/CHANGELOG.md) for details.
112
+
113
+ ## Documentation
114
+
115
+ - [Documentation](https://docs.leapocr.com)
116
+ - [Examples](https://github.com/leapocr/leapocr-python/tree/main/examples)
117
+
118
+ ---
119
+
120
+ **Full Changelog**: https://github.com/leapocr/leapocr-python/compare/v${{ steps.extract-notes.outputs.version }}...HEAD
121
+ draft: false
122
+ prerelease: false
123
+ generate_release_notes: true
@@ -0,0 +1,216 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+
204
+ # Ruff stuff:
205
+ .ruff_cache/
206
+
207
+ # PyPI configuration file
208
+ .pypirc
209
+
210
+ # Marimo
211
+ marimo/_static/
212
+ marimo/_lsp/
213
+ __marimo__/
214
+
215
+ # Streamlit
216
+ .streamlit/secrets.toml
@@ -0,0 +1 @@
1
+ 3.12