lightapi 0.1.1__tar.gz → 0.1.3__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.
- {lightapi-0.1.1 → lightapi-0.1.3}/.github/workflows/python-publish.yml +53 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/.github/workflows/test-dev.yml +11 -5
- lightapi-0.1.3/PKG-INFO +207 -0
- lightapi-0.1.3/README.md +156 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/auth_example.py +59 -43
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/basic_rest_api.py +12 -9
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/caching_example.py +73 -77
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/custom_snippet.py +45 -25
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/example.py +22 -22
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/filtering_pagination_example.py +202 -93
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/middleware_example.py +80 -72
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/relationships_example.py +239 -165
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/swagger_example.py +87 -80
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/user_goal_example.py +46 -33
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/validation_example.py +29 -23
- lightapi-0.1.3/lightapi/__init__.py +30 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/auth.py +26 -34
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/base_endpoint.py +6 -6
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/cache.py +15 -15
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/config.py +29 -15
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/core.py +172 -169
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/database.py +9 -7
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/exceptions.py +3 -3
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/filters.py +11 -13
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/handlers.py +29 -29
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/lightapi.py +1 -1
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/models.py +28 -24
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/pagination.py +13 -13
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/rest.py +79 -72
- {lightapi-0.1.1 → lightapi-0.1.3}/lightapi/swagger.py +41 -31
- {lightapi-0.1.1 → lightapi-0.1.3}/pyproject.toml +1 -1
- lightapi-0.1.3/test_simple_response.py +16 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/conftest.py +23 -24
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_additional_features.py +29 -26
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_auth.py +6 -3
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_auth_example.py +124 -128
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_basic_rest_api.py +50 -52
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_cache.py +9 -7
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_caching_example.py +180 -171
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_core.py +25 -15
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_custom_snippet.py +61 -43
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_example.py +11 -9
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_filtering_pagination_example.py +186 -152
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_filters.py +3 -1
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_helpers.py +13 -9
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_integration.py +27 -21
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_middleware.py +5 -3
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_middleware_example.py +121 -116
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_pagination.py +5 -3
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_rest.py +39 -31
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_swagger.py +11 -13
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_validation_example.py +13 -13
- lightapi-0.1.1/PKG-INFO +0 -1231
- lightapi-0.1.1/README.md +0 -1180
- lightapi-0.1.1/lightapi/__init__.py +0 -24
- lightapi-0.1.1/test_simple_response.py +0 -14
- {lightapi-0.1.1 → lightapi-0.1.3}/.github/workflows/pages-publish.yml +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/.gitignore +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/.idx/dev.nix +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/LICENSE +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/authentication.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/caching.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/filtering.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/middleware.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/pagination.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/advanced/validation.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/auth.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/cache.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/core.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/database.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/exceptions.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/filters.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/index.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/models.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/pagination.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/rest.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/swagger.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/api-reference/validation.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/deployment/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/deployment/docker.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/deployment/production.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/deployment/security.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/auth.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/basic-crud.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/basic-rest.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/caching.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/custom-application.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/filtering-pagination.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/middleware.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/examples/validation.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/configuration.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/first-steps.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/installation.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/introduction.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/getting-started/quickstart.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/index.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/cache.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/core-api.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/endpoints.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/handlers.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/middleware.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/technical-reference/models.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/troubleshooting.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/.pages +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/basic-api.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/database.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/endpoints.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/requests.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/docs/tutorial/responses.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/README.md +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/examples/__init__.py +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/mkdocs.yml +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/pytest.ini +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/requirements.txt +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/__init__.py +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/tests/test_clients.py +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/update_version.py +0 -0
- {lightapi-0.1.1 → lightapi-0.1.3}/uv.lock +0 -0
|
@@ -127,3 +127,56 @@ jobs:
|
|
|
127
127
|
git add pyproject.toml
|
|
128
128
|
git commit -m "Bump version to ${{ steps.update_version.outputs.new_version }}" || exit 0
|
|
129
129
|
git push
|
|
130
|
+
|
|
131
|
+
- name: Create Git Tag
|
|
132
|
+
run: |
|
|
133
|
+
git tag v${{ steps.update_version.outputs.new_version }}
|
|
134
|
+
git push origin v${{ steps.update_version.outputs.new_version }}
|
|
135
|
+
|
|
136
|
+
- name: Generate Release Notes
|
|
137
|
+
id: release_notes
|
|
138
|
+
run: |
|
|
139
|
+
# Get commits since last tag
|
|
140
|
+
LAST_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
|
|
141
|
+
if [ -z "$LAST_TAG" ]; then
|
|
142
|
+
# First release - get all commits
|
|
143
|
+
COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges HEAD~10..HEAD)
|
|
144
|
+
else
|
|
145
|
+
# Get commits since last tag
|
|
146
|
+
COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges $LAST_TAG..HEAD~1)
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Create release notes file
|
|
150
|
+
cat > release_notes.md << EOF
|
|
151
|
+
## 🚀 Release v${{ steps.update_version.outputs.new_version }}
|
|
152
|
+
|
|
153
|
+
### What's Changed
|
|
154
|
+
$COMMITS
|
|
155
|
+
|
|
156
|
+
### 📦 Installation
|
|
157
|
+
\`\`\`bash
|
|
158
|
+
pip install lightapi==${{ steps.update_version.outputs.new_version }}
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
### 📖 Documentation
|
|
162
|
+
- [Getting Started](https://iklobato.github.io/lightapi/getting-started/installation/)
|
|
163
|
+
- [API Reference](https://iklobato.github.io/lightapi/api-reference/core/)
|
|
164
|
+
- [Examples](https://iklobato.github.io/lightapi/examples/basic-rest/)
|
|
165
|
+
|
|
166
|
+
**Full Changelog**: https://github.com/iklobato/lightapi/compare/${LAST_TAG}...v${{ steps.update_version.outputs.new_version }}
|
|
167
|
+
EOF
|
|
168
|
+
|
|
169
|
+
echo "Generated release notes for v${{ steps.update_version.outputs.new_version }}"
|
|
170
|
+
|
|
171
|
+
- name: Create GitHub Release
|
|
172
|
+
uses: softprops/action-gh-release@v1
|
|
173
|
+
with:
|
|
174
|
+
tag_name: v${{ steps.update_version.outputs.new_version }}
|
|
175
|
+
name: "LightAPI v${{ steps.update_version.outputs.new_version }}"
|
|
176
|
+
body_path: release_notes.md
|
|
177
|
+
draft: false
|
|
178
|
+
prerelease: false
|
|
179
|
+
files: |
|
|
180
|
+
dist/lightapi-${{ steps.update_version.outputs.new_version }}-py3-none-any.whl
|
|
181
|
+
dist/lightapi-${{ steps.update_version.outputs.new_version }}.tar.gz
|
|
182
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -38,14 +38,20 @@ jobs:
|
|
|
38
38
|
# Install linting tools
|
|
39
39
|
pip install black isort flake8 mypy
|
|
40
40
|
|
|
41
|
-
# Run code formatting checks
|
|
42
|
-
|
|
41
|
+
# Run code formatting checks (warn only in development)
|
|
42
|
+
echo "🔍 Checking code formatting..."
|
|
43
|
+
black --check --diff . || echo "⚠️ Code formatting issues found, but not failing in development"
|
|
43
44
|
|
|
44
|
-
# Run import sorting checks
|
|
45
|
-
|
|
45
|
+
# Run import sorting checks (warn only in development)
|
|
46
|
+
echo "🔍 Checking import sorting..."
|
|
47
|
+
isort --check-only --diff . || echo "⚠️ Import sorting issues found, but not failing in development"
|
|
46
48
|
|
|
47
|
-
# Run style checks
|
|
49
|
+
# Run style checks (errors only)
|
|
50
|
+
echo "🔍 Checking critical style issues..."
|
|
48
51
|
flake8 lightapi/ --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
52
|
+
|
|
53
|
+
# Run additional style checks (warnings only)
|
|
54
|
+
echo "🔍 Checking style guidelines..."
|
|
49
55
|
flake8 lightapi/ --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
|
|
50
56
|
|
|
51
57
|
- name: Run tests
|
lightapi-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lightapi
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: A lightweight framework for building API endpoints using Python's native libraries.
|
|
5
|
+
Project-URL: Repository, https://github.com/henriqueblobato/LightApi
|
|
6
|
+
Project-URL: Issues, https://github.com/henriqueblobato/LightApi/issues
|
|
7
|
+
Project-URL: Homepage, https://github.com/henriqueblobato/LightApi
|
|
8
|
+
Author-email: iklobato <iklobato1@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,endpoint,framework,lightweight,rest,restful
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
22
|
+
Requires-Python: >=3.8.1
|
|
23
|
+
Requires-Dist: aiohttp<4.0.0,>=3.9.5
|
|
24
|
+
Requires-Dist: pyjwt<3.0.0,>=2.8.0
|
|
25
|
+
Requires-Dist: redis<6.0.0,>=5.0.0
|
|
26
|
+
Requires-Dist: sqlalchemy<3.0.0,>=2.0.30
|
|
27
|
+
Requires-Dist: starlette<1.0.0,>=0.37.0
|
|
28
|
+
Requires-Dist: uvicorn<1.0.0,>=0.30.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: black<24.0.0,>=23.3.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: flake8<7.0.0,>=6.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: isort<6.0.0,>=5.12.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: mypy<2.0.0,>=1.3.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest<8.0.0,>=7.3.1; extra == 'dev'
|
|
35
|
+
Provides-Extra: docs
|
|
36
|
+
Requires-Dist: mkdocs-awesome-pages-plugin; extra == 'docs'
|
|
37
|
+
Requires-Dist: mkdocs-git-authors-plugin; extra == 'docs'
|
|
38
|
+
Requires-Dist: mkdocs-git-committers-plugin-2; extra == 'docs'
|
|
39
|
+
Requires-Dist: mkdocs-git-revision-date-localized-plugin; extra == 'docs'
|
|
40
|
+
Requires-Dist: mkdocs-glightbox; extra == 'docs'
|
|
41
|
+
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
42
|
+
Requires-Dist: mkdocstrings[python]; extra == 'docs'
|
|
43
|
+
Provides-Extra: test
|
|
44
|
+
Requires-Dist: httpx<1.0.0,>=0.27.0; extra == 'test'
|
|
45
|
+
Requires-Dist: pyjwt<3.0.0,>=2.8.0; extra == 'test'
|
|
46
|
+
Requires-Dist: pytest<8.0.0,>=7.3.1; extra == 'test'
|
|
47
|
+
Requires-Dist: redis<6.0.0,>=5.0.0; extra == 'test'
|
|
48
|
+
Requires-Dist: starlette<1.0.0,>=0.37.0; extra == 'test'
|
|
49
|
+
Requires-Dist: uvicorn<1.0.0,>=0.30.0; extra == 'test'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# LightAPI
|
|
53
|
+
|
|
54
|
+
[](https://badge.fury.io/py/lightapi)
|
|
55
|
+
[](https://www.python.org/downloads/)
|
|
56
|
+
[](https://opensource.org/licenses/MIT)
|
|
57
|
+
|
|
58
|
+
A lightweight, fast, and easy-to-use web API framework for Python with automatic REST endpoint generation, built-in authentication, caching, and more.
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- 🚀 **Zero-boilerplate REST APIs** - Automatically generate CRUD operations from SQLAlchemy models
|
|
63
|
+
- 🔐 **Built-in Authentication** - JWT authentication with automatic CORS handling
|
|
64
|
+
- ⚡ **High Performance** - Built on Starlette for async support and speed
|
|
65
|
+
- 💾 **Smart Caching** - Redis-based caching with automatic invalidation
|
|
66
|
+
- 📊 **Request Validation** - Automatic request validation and error handling
|
|
67
|
+
- 🔍 **Advanced Filtering** - Query filtering, pagination, and sorting out of the box
|
|
68
|
+
- 📖 **Auto Documentation** - Automatic OpenAPI/Swagger documentation generation
|
|
69
|
+
- 🔧 **Flexible Middleware** - Easy middleware system for custom logic
|
|
70
|
+
- 🗄️ **Database Integration** - Seamless SQLAlchemy integration with automatic table creation
|
|
71
|
+
- ⚙️ **Environment Configuration** - Easy configuration management
|
|
72
|
+
|
|
73
|
+
## Quick Start
|
|
74
|
+
|
|
75
|
+
### Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install lightapi
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Basic Usage
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from lightapi import LightApi
|
|
85
|
+
from lightapi.database import Base
|
|
86
|
+
from sqlalchemy import Column, Integer, String
|
|
87
|
+
|
|
88
|
+
# Define your model
|
|
89
|
+
class User(Base):
|
|
90
|
+
__tablename__ = "users"
|
|
91
|
+
|
|
92
|
+
id = Column(Integer, primary_key=True)
|
|
93
|
+
name = Column(String(50))
|
|
94
|
+
email = Column(String(100))
|
|
95
|
+
|
|
96
|
+
# Create API instance
|
|
97
|
+
app = LightApi()
|
|
98
|
+
|
|
99
|
+
# Register your model - automatically creates CRUD endpoints
|
|
100
|
+
app.register(User)
|
|
101
|
+
|
|
102
|
+
# Run the server
|
|
103
|
+
if __name__ == "__main__":
|
|
104
|
+
app.run()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
That's it! You now have a fully functional REST API with:
|
|
108
|
+
- `GET /users` - List all users with filtering and pagination
|
|
109
|
+
- `GET /users/{id}` - Get user by ID
|
|
110
|
+
- `POST /users` - Create new user
|
|
111
|
+
- `PUT /users/{id}` - Update user
|
|
112
|
+
- `DELETE /users/{id}` - Delete user
|
|
113
|
+
- `OPTIONS /users` - CORS preflight support
|
|
114
|
+
|
|
115
|
+
## Documentation
|
|
116
|
+
|
|
117
|
+
Visit our comprehensive documentation at: https://iklobato.github.io/lightapi/
|
|
118
|
+
|
|
119
|
+
- [Getting Started Guide](https://iklobato.github.io/lightapi/getting-started/installation/)
|
|
120
|
+
- [API Reference](https://iklobato.github.io/lightapi/api-reference/core/)
|
|
121
|
+
- [Examples](https://iklobato.github.io/lightapi/examples/basic-rest/)
|
|
122
|
+
|
|
123
|
+
## Advanced Features
|
|
124
|
+
|
|
125
|
+
### Authentication
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from lightapi.auth import JWTAuthentication
|
|
129
|
+
|
|
130
|
+
# Add JWT authentication
|
|
131
|
+
auth = JWTAuthentication(secret_key="your-secret-key")
|
|
132
|
+
app.add_middleware(auth)
|
|
133
|
+
|
|
134
|
+
# Protected endpoints automatically require valid JWT tokens
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Caching
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from lightapi.cache import RedisCache
|
|
141
|
+
|
|
142
|
+
# Add Redis caching
|
|
143
|
+
cache = RedisCache(host="localhost", port=6379)
|
|
144
|
+
app.register(User, cache=cache, cache_ttl=300) # 5 minutes TTL
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Validation
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from lightapi.rest import Validator
|
|
151
|
+
|
|
152
|
+
class UserValidator(Validator):
|
|
153
|
+
def validate_post(self, data):
|
|
154
|
+
if not data.get("email"):
|
|
155
|
+
raise ValueError("Email is required")
|
|
156
|
+
return data
|
|
157
|
+
|
|
158
|
+
app.register(User, validator=UserValidator())
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Middleware
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from lightapi.core import Middleware
|
|
165
|
+
|
|
166
|
+
class LoggingMiddleware(Middleware):
|
|
167
|
+
async def process(self, request, call_next):
|
|
168
|
+
print(f"Request: {request.method} {request.url}")
|
|
169
|
+
response = await call_next(request)
|
|
170
|
+
print(f"Response: {response.status_code}")
|
|
171
|
+
return response
|
|
172
|
+
|
|
173
|
+
app.add_middleware(LoggingMiddleware())
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Why LightAPI?
|
|
177
|
+
|
|
178
|
+
- **Rapid Development**: Get REST APIs running in minutes, not hours
|
|
179
|
+
- **Production Ready**: Built-in security, caching, and error handling
|
|
180
|
+
- **Flexible**: Customize every aspect while keeping defaults simple
|
|
181
|
+
- **Modern**: Async support, type hints, and contemporary Python practices
|
|
182
|
+
- **Well Documented**: Comprehensive docs with real-world examples
|
|
183
|
+
|
|
184
|
+
## Examples
|
|
185
|
+
|
|
186
|
+
Check out the [examples directory](./examples/) for complete applications:
|
|
187
|
+
|
|
188
|
+
- [Basic REST API](./examples/basic_rest_api.py) - Simple CRUD operations
|
|
189
|
+
- [Authentication](./examples/auth_example.py) - JWT authentication
|
|
190
|
+
- [Caching](./examples/caching_example.py) - Redis caching implementation
|
|
191
|
+
- [Validation](./examples/validation_example.py) - Request validation
|
|
192
|
+
- [Middleware](./examples/middleware_example.py) - Custom middleware
|
|
193
|
+
- [Filtering & Pagination](./examples/filtering_pagination_example.py) - Advanced queries
|
|
194
|
+
|
|
195
|
+
## Contributing
|
|
196
|
+
|
|
197
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
**LightAPI** - *Making web APIs light and fast* ⚡
|
|
206
|
+
|
|
207
|
+
<!-- Testing development pipeline -->
|
lightapi-0.1.3/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# LightAPI
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/lightapi)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
A lightweight, fast, and easy-to-use web API framework for Python with automatic REST endpoint generation, built-in authentication, caching, and more.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🚀 **Zero-boilerplate REST APIs** - Automatically generate CRUD operations from SQLAlchemy models
|
|
12
|
+
- 🔐 **Built-in Authentication** - JWT authentication with automatic CORS handling
|
|
13
|
+
- ⚡ **High Performance** - Built on Starlette for async support and speed
|
|
14
|
+
- 💾 **Smart Caching** - Redis-based caching with automatic invalidation
|
|
15
|
+
- 📊 **Request Validation** - Automatic request validation and error handling
|
|
16
|
+
- 🔍 **Advanced Filtering** - Query filtering, pagination, and sorting out of the box
|
|
17
|
+
- 📖 **Auto Documentation** - Automatic OpenAPI/Swagger documentation generation
|
|
18
|
+
- 🔧 **Flexible Middleware** - Easy middleware system for custom logic
|
|
19
|
+
- 🗄️ **Database Integration** - Seamless SQLAlchemy integration with automatic table creation
|
|
20
|
+
- ⚙️ **Environment Configuration** - Easy configuration management
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install lightapi
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Basic Usage
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from lightapi import LightApi
|
|
34
|
+
from lightapi.database import Base
|
|
35
|
+
from sqlalchemy import Column, Integer, String
|
|
36
|
+
|
|
37
|
+
# Define your model
|
|
38
|
+
class User(Base):
|
|
39
|
+
__tablename__ = "users"
|
|
40
|
+
|
|
41
|
+
id = Column(Integer, primary_key=True)
|
|
42
|
+
name = Column(String(50))
|
|
43
|
+
email = Column(String(100))
|
|
44
|
+
|
|
45
|
+
# Create API instance
|
|
46
|
+
app = LightApi()
|
|
47
|
+
|
|
48
|
+
# Register your model - automatically creates CRUD endpoints
|
|
49
|
+
app.register(User)
|
|
50
|
+
|
|
51
|
+
# Run the server
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
app.run()
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
That's it! You now have a fully functional REST API with:
|
|
57
|
+
- `GET /users` - List all users with filtering and pagination
|
|
58
|
+
- `GET /users/{id}` - Get user by ID
|
|
59
|
+
- `POST /users` - Create new user
|
|
60
|
+
- `PUT /users/{id}` - Update user
|
|
61
|
+
- `DELETE /users/{id}` - Delete user
|
|
62
|
+
- `OPTIONS /users` - CORS preflight support
|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
Visit our comprehensive documentation at: https://iklobato.github.io/lightapi/
|
|
67
|
+
|
|
68
|
+
- [Getting Started Guide](https://iklobato.github.io/lightapi/getting-started/installation/)
|
|
69
|
+
- [API Reference](https://iklobato.github.io/lightapi/api-reference/core/)
|
|
70
|
+
- [Examples](https://iklobato.github.io/lightapi/examples/basic-rest/)
|
|
71
|
+
|
|
72
|
+
## Advanced Features
|
|
73
|
+
|
|
74
|
+
### Authentication
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from lightapi.auth import JWTAuthentication
|
|
78
|
+
|
|
79
|
+
# Add JWT authentication
|
|
80
|
+
auth = JWTAuthentication(secret_key="your-secret-key")
|
|
81
|
+
app.add_middleware(auth)
|
|
82
|
+
|
|
83
|
+
# Protected endpoints automatically require valid JWT tokens
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Caching
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from lightapi.cache import RedisCache
|
|
90
|
+
|
|
91
|
+
# Add Redis caching
|
|
92
|
+
cache = RedisCache(host="localhost", port=6379)
|
|
93
|
+
app.register(User, cache=cache, cache_ttl=300) # 5 minutes TTL
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Validation
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from lightapi.rest import Validator
|
|
100
|
+
|
|
101
|
+
class UserValidator(Validator):
|
|
102
|
+
def validate_post(self, data):
|
|
103
|
+
if not data.get("email"):
|
|
104
|
+
raise ValueError("Email is required")
|
|
105
|
+
return data
|
|
106
|
+
|
|
107
|
+
app.register(User, validator=UserValidator())
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Middleware
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from lightapi.core import Middleware
|
|
114
|
+
|
|
115
|
+
class LoggingMiddleware(Middleware):
|
|
116
|
+
async def process(self, request, call_next):
|
|
117
|
+
print(f"Request: {request.method} {request.url}")
|
|
118
|
+
response = await call_next(request)
|
|
119
|
+
print(f"Response: {response.status_code}")
|
|
120
|
+
return response
|
|
121
|
+
|
|
122
|
+
app.add_middleware(LoggingMiddleware())
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Why LightAPI?
|
|
126
|
+
|
|
127
|
+
- **Rapid Development**: Get REST APIs running in minutes, not hours
|
|
128
|
+
- **Production Ready**: Built-in security, caching, and error handling
|
|
129
|
+
- **Flexible**: Customize every aspect while keeping defaults simple
|
|
130
|
+
- **Modern**: Async support, type hints, and contemporary Python practices
|
|
131
|
+
- **Well Documented**: Comprehensive docs with real-world examples
|
|
132
|
+
|
|
133
|
+
## Examples
|
|
134
|
+
|
|
135
|
+
Check out the [examples directory](./examples/) for complete applications:
|
|
136
|
+
|
|
137
|
+
- [Basic REST API](./examples/basic_rest_api.py) - Simple CRUD operations
|
|
138
|
+
- [Authentication](./examples/auth_example.py) - JWT authentication
|
|
139
|
+
- [Caching](./examples/caching_example.py) - Redis caching implementation
|
|
140
|
+
- [Validation](./examples/validation_example.py) - Request validation
|
|
141
|
+
- [Middleware](./examples/middleware_example.py) - Custom middleware
|
|
142
|
+
- [Filtering & Pagination](./examples/filtering_pagination_example.py) - Advanced queries
|
|
143
|
+
|
|
144
|
+
## Contributing
|
|
145
|
+
|
|
146
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
**LightAPI** - *Making web APIs light and fast* ⚡
|
|
155
|
+
|
|
156
|
+
<!-- Testing development pipeline -->
|
|
@@ -1,111 +1,121 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
import jwt
|
|
1
5
|
from sqlalchemy import Column, Integer, String
|
|
2
|
-
|
|
3
|
-
from lightapi.rest import RestEndpoint
|
|
6
|
+
|
|
4
7
|
from lightapi.auth import JWTAuthentication
|
|
5
|
-
from lightapi.models import Base, register_model_class
|
|
6
8
|
from lightapi.config import config
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
9
|
+
from lightapi.core import LightApi, Middleware, Response
|
|
10
|
+
from lightapi.models import Base, register_model_class
|
|
11
|
+
from lightapi.rest import RestEndpoint
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
# Custom authentication class
|
|
12
15
|
class CustomJWTAuth(JWTAuthentication):
|
|
13
16
|
def __init__(self):
|
|
14
17
|
super().__init__()
|
|
15
18
|
self.secret_key = config.jwt_secret
|
|
16
|
-
|
|
19
|
+
|
|
17
20
|
def authenticate(self, request):
|
|
18
21
|
# Use the parent class implementation
|
|
19
22
|
return super().authenticate(request)
|
|
20
23
|
|
|
24
|
+
|
|
21
25
|
# Login endpoint to get a token
|
|
22
26
|
class AuthEndpoint(RestEndpoint):
|
|
23
27
|
__abstract__ = True # Not a database model
|
|
24
|
-
|
|
28
|
+
|
|
25
29
|
def post(self, request):
|
|
26
|
-
data = getattr(request,
|
|
27
|
-
username = data.get(
|
|
28
|
-
password = data.get(
|
|
29
|
-
|
|
30
|
+
data = getattr(request, "data", {})
|
|
31
|
+
username = data.get("username")
|
|
32
|
+
password = data.get("password")
|
|
33
|
+
|
|
30
34
|
# Simple authentication (replace with database lookup in real apps)
|
|
31
35
|
if username == "admin" and password == "password":
|
|
32
36
|
# Create a JWT token
|
|
33
37
|
payload = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
"sub": "user_1",
|
|
39
|
+
"username": username,
|
|
40
|
+
"role": "admin",
|
|
41
|
+
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1),
|
|
38
42
|
}
|
|
39
43
|
token = jwt.encode(payload, config.jwt_secret, algorithm="HS256")
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
return {"token": token}, 200
|
|
42
46
|
else:
|
|
43
47
|
return Response({"error": "Invalid credentials"}, status_code=401)
|
|
44
48
|
|
|
49
|
+
|
|
45
50
|
# Protected resource that requires authentication
|
|
46
51
|
class SecretResource(RestEndpoint):
|
|
47
52
|
__abstract__ = True # Not a database model
|
|
48
|
-
|
|
53
|
+
|
|
49
54
|
class Configuration:
|
|
50
55
|
authentication_class = CustomJWTAuth
|
|
51
|
-
|
|
56
|
+
|
|
52
57
|
def get(self, request):
|
|
53
58
|
try:
|
|
54
59
|
# Access the user info stored during authentication
|
|
55
|
-
username = request.state.user.get(
|
|
56
|
-
role = request.state.user.get(
|
|
57
|
-
|
|
60
|
+
username = request.state.user.get("username")
|
|
61
|
+
role = request.state.user.get("role")
|
|
62
|
+
|
|
58
63
|
return {
|
|
59
64
|
"message": f"Hello, {username}! You have {role} access.",
|
|
60
|
-
"secret_data": "This is protected information"
|
|
65
|
+
"secret_data": "This is protected information",
|
|
61
66
|
}, 200
|
|
62
67
|
except Exception as e:
|
|
63
68
|
import traceback
|
|
69
|
+
|
|
64
70
|
print(f"Error in SecretResource.get: {e}")
|
|
65
71
|
print(traceback.format_exc())
|
|
66
72
|
return {"error": str(e)}, 500
|
|
67
73
|
|
|
74
|
+
|
|
68
75
|
# Public endpoint that doesn't require authentication
|
|
69
76
|
class PublicResource(RestEndpoint):
|
|
70
77
|
__abstract__ = True # Not a database model
|
|
71
|
-
|
|
78
|
+
|
|
72
79
|
def get(self, request):
|
|
73
80
|
try:
|
|
74
81
|
return {"message": "This is public information"}, 200
|
|
75
82
|
except Exception as e:
|
|
76
83
|
import traceback
|
|
84
|
+
|
|
77
85
|
print(f"Error in PublicResource.get: {e}")
|
|
78
86
|
print(traceback.format_exc())
|
|
79
87
|
return {"error": str(e)}, 500
|
|
80
88
|
|
|
89
|
+
|
|
81
90
|
# User profile endpoint that requires authentication
|
|
82
91
|
@register_model_class
|
|
83
92
|
class UserProfile(RestEndpoint):
|
|
84
|
-
__tablename__ =
|
|
85
|
-
|
|
93
|
+
__tablename__ = "user_profiles"
|
|
94
|
+
|
|
86
95
|
id = Column(Integer, primary_key=True)
|
|
87
96
|
user_id = Column(String(50))
|
|
88
97
|
full_name = Column(String(100))
|
|
89
98
|
email = Column(String(100))
|
|
90
|
-
|
|
99
|
+
|
|
91
100
|
class Configuration:
|
|
92
101
|
authentication_class = CustomJWTAuth
|
|
93
|
-
|
|
102
|
+
|
|
94
103
|
# Override GET to return only the current user's profile
|
|
95
104
|
def get(self, request):
|
|
96
|
-
user_id = request.state.user.get(
|
|
105
|
+
user_id = request.state.user.get("sub")
|
|
97
106
|
profile = self.session.query(self.__class__).filter_by(user_id=user_id).first()
|
|
98
|
-
|
|
107
|
+
|
|
99
108
|
if profile:
|
|
100
109
|
return {
|
|
101
110
|
"id": profile.id,
|
|
102
111
|
"user_id": profile.user_id,
|
|
103
112
|
"full_name": profile.full_name,
|
|
104
|
-
"email": profile.email
|
|
113
|
+
"email": profile.email,
|
|
105
114
|
}, 200
|
|
106
115
|
else:
|
|
107
116
|
return Response({"error": "Profile not found"}, status_code=404)
|
|
108
117
|
|
|
118
|
+
|
|
109
119
|
if __name__ == "__main__":
|
|
110
120
|
app = LightApi(
|
|
111
121
|
database_url="sqlite:///auth_example.db",
|
|
@@ -113,19 +123,25 @@ if __name__ == "__main__":
|
|
|
113
123
|
swagger_version="1.0.0",
|
|
114
124
|
swagger_description="Example showing JWT authentication with LightAPI",
|
|
115
125
|
)
|
|
116
|
-
|
|
117
|
-
app.register(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
|
|
127
|
+
app.register(
|
|
128
|
+
{
|
|
129
|
+
"/auth/login": AuthEndpoint,
|
|
130
|
+
"/public": PublicResource,
|
|
131
|
+
"/secret": SecretResource,
|
|
132
|
+
"/profile": UserProfile,
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
124
136
|
print("Server running at http://localhost:8000")
|
|
125
137
|
print("API documentation available at http://localhost:8000/docs")
|
|
126
138
|
print("\nTo get a token:")
|
|
127
|
-
print(
|
|
139
|
+
print(
|
|
140
|
+
'curl -X POST http://localhost:8000/auth/login -H \'Content-Type: application/json\' -d \'{"username": "admin", "password": "password"}\''
|
|
141
|
+
)
|
|
128
142
|
print("\nTo access protected resource:")
|
|
129
|
-
print(
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
print(
|
|
144
|
+
"curl -X GET http://localhost:8000/secret -H 'Authorization: Bearer YOUR_TOKEN'"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
app.run(host="localhost", port=8000, debug=True)
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
from sqlalchemy import Column, Integer, String
|
|
2
|
+
|
|
2
3
|
from lightapi.core import LightApi
|
|
3
|
-
from lightapi.rest import RestEndpoint
|
|
4
4
|
from lightapi.models import Base, register_model_class
|
|
5
|
+
from lightapi.rest import RestEndpoint
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
# Define a model that inherits from RestEndpoint
|
|
7
9
|
@register_model_class
|
|
8
10
|
class User(RestEndpoint):
|
|
9
|
-
__tablename__ =
|
|
10
|
-
|
|
11
|
+
__tablename__ = "users"
|
|
12
|
+
|
|
11
13
|
id = Column(Integer, primary_key=True)
|
|
12
14
|
name = Column(String(100))
|
|
13
15
|
email = Column(String(100))
|
|
14
16
|
role = Column(String(50))
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
# The default implementation already includes:
|
|
17
19
|
# - GET: List all users or get a specific user by ID
|
|
18
20
|
# - POST: Create a new user
|
|
@@ -20,6 +22,7 @@ class User(RestEndpoint):
|
|
|
20
22
|
# - DELETE: Delete a user
|
|
21
23
|
# - OPTIONS: Return allowed methods
|
|
22
24
|
|
|
25
|
+
|
|
23
26
|
if __name__ == "__main__":
|
|
24
27
|
# Initialize the API with SQLite database
|
|
25
28
|
app = LightApi(
|
|
@@ -28,12 +31,12 @@ if __name__ == "__main__":
|
|
|
28
31
|
swagger_version="1.0.0",
|
|
29
32
|
swagger_description="Simple REST API demonstrating basic CRUD operations",
|
|
30
33
|
)
|
|
31
|
-
|
|
34
|
+
|
|
32
35
|
# Register our endpoint
|
|
33
|
-
app.register({
|
|
34
|
-
|
|
36
|
+
app.register({"/users": User})
|
|
37
|
+
|
|
35
38
|
print("Server running at http://localhost:8000")
|
|
36
39
|
print("API documentation available at http://localhost:8000/docs")
|
|
37
|
-
|
|
40
|
+
|
|
38
41
|
# Run the server
|
|
39
|
-
app.run(host="localhost", port=8000, debug=True)
|
|
42
|
+
app.run(host="localhost", port=8000, debug=True)
|