| Name | secure-api-py JSON |
| Version |
2.0.1
JSON |
| download |
| home_page | None |
| Summary | A lightweight, modular, and secure framework designed for building RESTful APIs in Appwrite Functions. It provides a streamlined development experience with built-in utilities for request handling, validation, authentication, and database interactions. |
| upload_time | 2025-11-09 16:17:23 |
| maintainer | None |
| docs_url | None |
| author | MarcusXTechnologies |
| requires_python | >=3.8 |
| license | BSD-3-Clause |
| keywords |
appwrite
api
rest
framework
functions
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# SecureAPI-Py - A Secure RESTful API Framework for Appwrite Functions
**`SecureAPI-Py`** is a lightweight, modular, and secure framework designed for building RESTful APIs in Appwrite Functions using Python. It provides a streamlined development experience with built-in utilities for request handling, validation, authentication, and database interactions.
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Core Library](#core-library-secureapi)
- [Utility Modules](#utility-modules)
- [Middleware](#middleware)
- [Real-World Example](#real-world-example)
- [Configuration](#configuration)
- [API Reference](#api-reference)
- [Contributing](#contributing)
- [License](#license)
## Features
- **Core Library**: Simplifies request/response handling, error management, and enhanced logging with pretty-print support.
- **Utility Modules**:
- **Validator**: Ensures input integrity by validating headers, query parameters, and body content.
- **Security**: Provides JWT validation and API key verification.
- **DatabaseManager**: Facilitates CRUD operations on Appwrite databases with flexible database ID management.
- **Enhanced Logging**: Pretty-print JSON/dicts with proper formatting for better debugging.
- **Middleware Support**: Customize request processing with authentication, logging, CORS, and validation middleware.
- **Helper Properties**: Convenient properties for accessing Appwrite Function metadata, user info, and environment variables.
- **Response Types**: Support for all Appwrite Function response types (JSON, text, binary, redirect, empty).
- **Router**: Simple routing system for handling multiple endpoints.
## Installation
To use `SecureAPI-Py` in your Appwrite function, add it to your `requirements.txt` file:
```txt
secure-api-py>=1.0.0
appwrite>=7.0.0
```
Then, install the dependencies:
```bash
pip install -r requirements.txt
```
## Getting Started
### Core Library: `SecureAPI`
#### Usage
The `SecureAPI` class is your entry point to build APIs. It handles request processing and provides utility methods for standardized responses.
#### Example:
```python
from secure_api import SecureAPI
def main(context):
# Option 1: Initialize with a default database ID
api = SecureAPI(context, database_id='YOUR_DATABASE_ID')
# Option 2: Initialize without default database ID (flexible approach)
# api = SecureAPI(context)
if api.context.req.path == '/tasks/create' and api.method == 'POST':
# Add task creation logic here
return api.send_success(message='Task created', data=task_doc)
```
### Utility Modules
#### Validator
Ensures your API receives valid input.
```python
from secure_api import Validator
async def input_validator(api):
Validator.validate_headers(api.headers, ['x-api-key'])
Validator.validate_query_params(api.query_params, ['type'])
api.log('Input validation passed.')
```
#### Security
Handle authentication via JWTs or API keys.
```python
from secure_api import Security, auth_middleware
# Use built-in auth middleware
api.use_middleware(auth_middleware)
# Or create custom authentication
async def custom_auth(api):
headers = api.headers
if 'x-api-key' not in headers or not headers['x-api-key']:
raise Exception('Missing `x-api-key` header.')
jwt = headers['x-api-key']
security = Security(api.client)
try:
is_authenticated = await security.validate_jwt(jwt)
api.log(f'User authenticated: {is_authenticated}')
except Exception as e:
api.error(f'Authentication failed: {e}')
raise Exception('Invalid or expired token.')
```
#### DatabaseManager
Simplifies CRUD operations for Appwrite collections with flexible database management.
```python
async def create_task(api):
task_doc = await api.db.create_document(
collection_id='tasks',
data=task,
database_id='YOUR_DATABASE_ID'
)
return await api.send_success(message='Task created', data=task_doc)
```
**Key Features:**
- **Flexible Database IDs**: Use different databases dynamically
- **Named Parameters**: Clean, readable function calls
- **Backward Compatibility**: Existing code continues to work via `api.db_helper` (deprecated)
### Enhanced Logging
The improved logging system now properly formats objects and dicts for better debugging:
```python
# Simple logging
api.log('Processing request...')
# Pretty-print JSON objects
api.log_json('User Data', {
'id': '123',
'name': 'John Doe',
'permissions': ['read', 'write'],
})
# Automatic formatting for dicts/lists
api.log({
'status': 'success',
'count': 42,
'items': ['item1', 'item2']
})
# Output will be properly indented JSON
```
### Helper Properties
SecureAPI includes convenient helper properties for common Appwrite Function patterns:
```python
# Request helpers
api.path # Request path
api.url # Full URL
api.host # Hostname
api.method # HTTP method
# Authentication helpers
api.user_id # User ID if authenticated
api.user_jwt # JWT token if available
api.is_authenticated # Check if user is authenticated
# Function metadata
api.trigger_type # How function was triggered (http, schedule, event)
api.trigger_event # Event that triggered the function
# Environment variables with defaults
api.get_env('MY_VAR', default_value='default')
```
### Response Types
Support for all Appwrite Function response types:
```python
# JSON responses
await api.send_success(message='Success', data={...})
await api.send_error(message='Error', status_code=500)
# Other response types
await api.send_empty() # 204 No Content
await api.send_text('Plain text', status_code=200)
await api.send_redirect('https://example.com') # 301 Redirect
await api.send_binary(bytes_data) # Binary data
```
### Middleware
Middleware functions process requests before hitting route handlers:
#### Built-in Middleware
1. **CORS Middleware**:
```python
from secure_api import cors_middleware
api.use_middleware(cors_middleware(
origin='*',
methods='GET, POST, PUT, DELETE, OPTIONS',
headers='Content-Type, Authorization',
))
```
2. **Logging Request Middleware** (with enhanced formatting):
```python
from secure_api import log_request
api.use_middleware(log_request) # Now with pretty-print support!
```
3. **Authentication Middleware**:
```python
from secure_api import auth_middleware
api.use_middleware(auth_middleware)
```
4. **Rate Limiting Middleware**:
```python
from secure_api import rate_limit_middleware
api.use_middleware(rate_limit_middleware(
max_requests=100,
window_minutes=1
))
```
#### Adding Middleware (Order Matters!)
```python
api.use_middleware(cors_middleware()) # Handle CORS first
api.use_middleware(log_request) # Then log requests
api.use_middleware(auth_middleware) # Then check auth
```
### Router
Use the built-in router for handling multiple endpoints:
```python
from secure_api import SecureAPI, Router
async def main(context):
api = SecureAPI(context, database_id='YOUR_DATABASE_ID')
router = Router()
# Define routes
router.get('/tasks', list_tasks)
router.post('/tasks', create_task)
router.put('/tasks/:id', update_task)
router.delete('/tasks/:id', delete_task)
# Execute middleware
await api.execute_middleware()
# Handle request
return await router.handle(api)
async def list_tasks(api, params):
tasks = await api.db.list_documents(collection_id='tasks')
return await api.send_success(message='Tasks retrieved', data={'tasks': tasks})
async def create_task(api, params):
api.validate_body({'title': 'required|string', 'description': 'required|string'})
task = {
'title': api.body_json['title'],
'description': api.body_json['description'],
'completed': False,
}
task_doc = await api.db.create_document(collection_id='tasks', data=task)
return await api.send_success(message='Task created', data=task_doc)
async def update_task(api, params):
task_id = params['id']
data = api.body_json
task_doc = await api.db.update_document(
collection_id='tasks',
document_id=task_id,
data=data
)
return await api.send_success(message='Task updated', data=task_doc)
async def delete_task(api, params):
task_id = params['id']
await api.db.delete_document(collection_id='tasks', document_id=task_id)
return await api.send_success(message='Task deleted')
```
### Real-World Example: Task Management System
#### Endpoints
1. **Create Task**: `POST /tasks/create`
2. **List Tasks**: `GET /tasks/get`
3. **Update Task**: `PUT /tasks/update`
4. **Delete Task**: `DELETE /tasks/delete`
#### Example Implementation
```python
from secure_api import SecureAPI, log_request, auth_middleware, Validator
async def main(context):
# Flexible initialization - can work with or without default database ID
api = SecureAPI(context)
# Middleware
api.use_middleware(log_request)
api.use_middleware(auth_middleware)
# Handle requests
try:
await api.execute_middleware()
path = api.context.req.path
if path == '/tasks/create' and api.method == 'POST':
return await create_task(api)
elif path == '/tasks/get' and api.method == 'GET':
return await list_tasks(api)
elif path == '/tasks/update' and api.method == 'PUT':
return await update_task(api)
elif path == '/tasks/delete' and api.method == 'DELETE':
return await delete_task(api)
else:
return await api.send_error(
message='Endpoint not found',
status_code=404,
)
except Exception as e:
api.error(f'Error: {e}')
return await api.handle_error(e)
async def create_task(api):
Validator.validate_body(api.body_json, ['title', 'description'])
task = {
'title': api.body_json['title'],
'description': api.body_json['description'],
'completed': False,
}
task_doc = await api.db.create_document(
collection_id='tasks',
data=task,
database_id='YOUR_DATABASE_ID'
)
return await api.send_success(message='Task created', data=task_doc)
async def list_tasks(api):
tasks = await api.db.list_documents(
collection_id='tasks',
database_id='YOUR_DATABASE_ID'
)
return await api.send_success(message='Tasks retrieved', data={'tasks': tasks})
```
## Configuration
Configure your Appwrite function to use `SecureAPI-Py` by setting up the necessary environment variables and dependencies as described in the [Getting Started](#getting-started) section.
## API Reference
### SecureAPI Class
Main class for handling requests and responses.
**Methods:**
- `log(message)` - Log a message
- `error(message)` - Log an error
- `log_json(label, data)` - Log JSON with label
- `send_success(...)` - Send success response
- `send_error(...)` - Send error response
- `send_unauthorized(...)` - Send 401 response
- `send_empty()` - Send 204 response
- `send_redirect(url)` - Send redirect response
- `send_text(text)` - Send text response
- `send_binary(bytes)` - Send binary response
- `validate_body(rules)` - Validate request body
- `handle_error(error)` - Handle errors
**Properties:**
- `method` - HTTP method
- `headers` - Request headers
- `query_params` - Query parameters
- `body_text` - Request body as text
- `body_json` - Request body as JSON
- `path` - Request path
- `url` - Request URL
- `user_id` - Authenticated user ID
- `is_authenticated` - Authentication status
## Contributing
Contributions are welcome! Please submit pull requests or open issues for suggestions.
## License
This package is distributed under the BSD-3-Clause License.
Raw data
{
"_id": null,
"home_page": null,
"name": "secure-api-py",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "appwrite, api, rest, framework, functions",
"author": "MarcusXTechnologies",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/45/61/5ca25c2d2069ea0cbf437217fbb65391fe7c0778b7734fd4b552f3e10b63/secure_api_py-2.0.1.tar.gz",
"platform": null,
"description": "# SecureAPI-Py - A Secure RESTful API Framework for Appwrite Functions\n\n**`SecureAPI-Py`** is a lightweight, modular, and secure framework designed for building RESTful APIs in Appwrite Functions using Python. It provides a streamlined development experience with built-in utilities for request handling, validation, authentication, and database interactions.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n - [Core Library](#core-library-secureapi)\n - [Utility Modules](#utility-modules)\n - [Middleware](#middleware)\n - [Real-World Example](#real-world-example)\n- [Configuration](#configuration)\n- [API Reference](#api-reference)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n- **Core Library**: Simplifies request/response handling, error management, and enhanced logging with pretty-print support.\n- **Utility Modules**:\n - **Validator**: Ensures input integrity by validating headers, query parameters, and body content.\n - **Security**: Provides JWT validation and API key verification.\n - **DatabaseManager**: Facilitates CRUD operations on Appwrite databases with flexible database ID management.\n- **Enhanced Logging**: Pretty-print JSON/dicts with proper formatting for better debugging.\n- **Middleware Support**: Customize request processing with authentication, logging, CORS, and validation middleware.\n- **Helper Properties**: Convenient properties for accessing Appwrite Function metadata, user info, and environment variables.\n- **Response Types**: Support for all Appwrite Function response types (JSON, text, binary, redirect, empty).\n- **Router**: Simple routing system for handling multiple endpoints.\n\n## Installation\n\nTo use `SecureAPI-Py` in your Appwrite function, add it to your `requirements.txt` file:\n\n```txt\nsecure-api-py>=1.0.0\nappwrite>=7.0.0\n```\n\nThen, install the dependencies:\n\n```bash\npip install -r requirements.txt\n```\n\n## Getting Started\n\n### Core Library: `SecureAPI`\n\n#### Usage\n\nThe `SecureAPI` class is your entry point to build APIs. It handles request processing and provides utility methods for standardized responses.\n\n#### Example:\n\n```python\nfrom secure_api import SecureAPI\n\ndef main(context):\n # Option 1: Initialize with a default database ID\n api = SecureAPI(context, database_id='YOUR_DATABASE_ID')\n \n # Option 2: Initialize without default database ID (flexible approach)\n # api = SecureAPI(context)\n \n if api.context.req.path == '/tasks/create' and api.method == 'POST':\n # Add task creation logic here\n return api.send_success(message='Task created', data=task_doc)\n```\n\n### Utility Modules\n\n#### Validator\n\nEnsures your API receives valid input.\n\n```python\nfrom secure_api import Validator\n\nasync def input_validator(api):\n Validator.validate_headers(api.headers, ['x-api-key'])\n Validator.validate_query_params(api.query_params, ['type'])\n api.log('Input validation passed.')\n```\n\n#### Security\n\nHandle authentication via JWTs or API keys.\n\n```python\nfrom secure_api import Security, auth_middleware\n\n# Use built-in auth middleware\napi.use_middleware(auth_middleware)\n\n# Or create custom authentication\nasync def custom_auth(api):\n headers = api.headers\n \n if 'x-api-key' not in headers or not headers['x-api-key']:\n raise Exception('Missing `x-api-key` header.')\n \n jwt = headers['x-api-key']\n security = Security(api.client)\n \n try:\n is_authenticated = await security.validate_jwt(jwt)\n api.log(f'User authenticated: {is_authenticated}')\n except Exception as e:\n api.error(f'Authentication failed: {e}')\n raise Exception('Invalid or expired token.')\n```\n\n#### DatabaseManager\n\nSimplifies CRUD operations for Appwrite collections with flexible database management.\n\n```python\nasync def create_task(api):\n task_doc = await api.db.create_document(\n collection_id='tasks',\n data=task,\n database_id='YOUR_DATABASE_ID'\n )\n return await api.send_success(message='Task created', data=task_doc)\n```\n\n**Key Features:**\n- **Flexible Database IDs**: Use different databases dynamically\n- **Named Parameters**: Clean, readable function calls\n- **Backward Compatibility**: Existing code continues to work via `api.db_helper` (deprecated)\n\n### Enhanced Logging\n\nThe improved logging system now properly formats objects and dicts for better debugging:\n\n```python\n# Simple logging\napi.log('Processing request...')\n\n# Pretty-print JSON objects\napi.log_json('User Data', {\n 'id': '123',\n 'name': 'John Doe',\n 'permissions': ['read', 'write'],\n})\n\n# Automatic formatting for dicts/lists\napi.log({\n 'status': 'success',\n 'count': 42,\n 'items': ['item1', 'item2']\n})\n# Output will be properly indented JSON\n```\n\n### Helper Properties\n\nSecureAPI includes convenient helper properties for common Appwrite Function patterns:\n\n```python\n# Request helpers\napi.path # Request path\napi.url # Full URL \napi.host # Hostname\napi.method # HTTP method\n\n# Authentication helpers\napi.user_id # User ID if authenticated\napi.user_jwt # JWT token if available\napi.is_authenticated # Check if user is authenticated\n\n# Function metadata\napi.trigger_type # How function was triggered (http, schedule, event)\napi.trigger_event # Event that triggered the function\n\n# Environment variables with defaults\napi.get_env('MY_VAR', default_value='default')\n```\n\n### Response Types\n\nSupport for all Appwrite Function response types:\n\n```python\n# JSON responses\nawait api.send_success(message='Success', data={...})\nawait api.send_error(message='Error', status_code=500)\n\n# Other response types\nawait api.send_empty() # 204 No Content\nawait api.send_text('Plain text', status_code=200)\nawait api.send_redirect('https://example.com') # 301 Redirect\nawait api.send_binary(bytes_data) # Binary data\n```\n\n### Middleware\n\nMiddleware functions process requests before hitting route handlers:\n\n#### Built-in Middleware\n\n1. **CORS Middleware**:\n```python\nfrom secure_api import cors_middleware\n\napi.use_middleware(cors_middleware(\n origin='*',\n methods='GET, POST, PUT, DELETE, OPTIONS',\n headers='Content-Type, Authorization',\n))\n```\n\n2. **Logging Request Middleware** (with enhanced formatting):\n```python\nfrom secure_api import log_request\n\napi.use_middleware(log_request) # Now with pretty-print support!\n```\n\n3. **Authentication Middleware**:\n```python\nfrom secure_api import auth_middleware\n\napi.use_middleware(auth_middleware)\n```\n\n4. **Rate Limiting Middleware**:\n```python\nfrom secure_api import rate_limit_middleware\n\napi.use_middleware(rate_limit_middleware(\n max_requests=100,\n window_minutes=1\n))\n```\n\n#### Adding Middleware (Order Matters!)\n\n```python\napi.use_middleware(cors_middleware()) # Handle CORS first\napi.use_middleware(log_request) # Then log requests\napi.use_middleware(auth_middleware) # Then check auth\n```\n\n### Router\n\nUse the built-in router for handling multiple endpoints:\n\n```python\nfrom secure_api import SecureAPI, Router\n\nasync def main(context):\n api = SecureAPI(context, database_id='YOUR_DATABASE_ID')\n router = Router()\n \n # Define routes\n router.get('/tasks', list_tasks)\n router.post('/tasks', create_task)\n router.put('/tasks/:id', update_task)\n router.delete('/tasks/:id', delete_task)\n \n # Execute middleware\n await api.execute_middleware()\n \n # Handle request\n return await router.handle(api)\n\nasync def list_tasks(api, params):\n tasks = await api.db.list_documents(collection_id='tasks')\n return await api.send_success(message='Tasks retrieved', data={'tasks': tasks})\n\nasync def create_task(api, params):\n api.validate_body({'title': 'required|string', 'description': 'required|string'})\n task = {\n 'title': api.body_json['title'],\n 'description': api.body_json['description'],\n 'completed': False,\n }\n task_doc = await api.db.create_document(collection_id='tasks', data=task)\n return await api.send_success(message='Task created', data=task_doc)\n\nasync def update_task(api, params):\n task_id = params['id']\n data = api.body_json\n task_doc = await api.db.update_document(\n collection_id='tasks',\n document_id=task_id,\n data=data\n )\n return await api.send_success(message='Task updated', data=task_doc)\n\nasync def delete_task(api, params):\n task_id = params['id']\n await api.db.delete_document(collection_id='tasks', document_id=task_id)\n return await api.send_success(message='Task deleted')\n```\n\n### Real-World Example: Task Management System\n\n#### Endpoints\n\n1. **Create Task**: `POST /tasks/create`\n2. **List Tasks**: `GET /tasks/get`\n3. **Update Task**: `PUT /tasks/update`\n4. **Delete Task**: `DELETE /tasks/delete`\n\n#### Example Implementation\n\n```python\nfrom secure_api import SecureAPI, log_request, auth_middleware, Validator\n\nasync def main(context):\n # Flexible initialization - can work with or without default database ID\n api = SecureAPI(context)\n \n # Middleware\n api.use_middleware(log_request)\n api.use_middleware(auth_middleware)\n \n # Handle requests\n try:\n await api.execute_middleware()\n path = api.context.req.path\n \n if path == '/tasks/create' and api.method == 'POST':\n return await create_task(api)\n elif path == '/tasks/get' and api.method == 'GET':\n return await list_tasks(api)\n elif path == '/tasks/update' and api.method == 'PUT':\n return await update_task(api)\n elif path == '/tasks/delete' and api.method == 'DELETE':\n return await delete_task(api)\n else:\n return await api.send_error(\n message='Endpoint not found',\n status_code=404,\n )\n except Exception as e:\n api.error(f'Error: {e}')\n return await api.handle_error(e)\n\nasync def create_task(api):\n Validator.validate_body(api.body_json, ['title', 'description'])\n task = {\n 'title': api.body_json['title'],\n 'description': api.body_json['description'],\n 'completed': False,\n }\n \n task_doc = await api.db.create_document(\n collection_id='tasks',\n data=task,\n database_id='YOUR_DATABASE_ID'\n )\n return await api.send_success(message='Task created', data=task_doc)\n\nasync def list_tasks(api):\n tasks = await api.db.list_documents(\n collection_id='tasks',\n database_id='YOUR_DATABASE_ID'\n )\n return await api.send_success(message='Tasks retrieved', data={'tasks': tasks})\n```\n\n## Configuration\n\nConfigure your Appwrite function to use `SecureAPI-Py` by setting up the necessary environment variables and dependencies as described in the [Getting Started](#getting-started) section.\n\n## API Reference\n\n### SecureAPI Class\n\nMain class for handling requests and responses.\n\n**Methods:**\n- `log(message)` - Log a message\n- `error(message)` - Log an error\n- `log_json(label, data)` - Log JSON with label\n- `send_success(...)` - Send success response\n- `send_error(...)` - Send error response\n- `send_unauthorized(...)` - Send 401 response\n- `send_empty()` - Send 204 response\n- `send_redirect(url)` - Send redirect response\n- `send_text(text)` - Send text response\n- `send_binary(bytes)` - Send binary response\n- `validate_body(rules)` - Validate request body\n- `handle_error(error)` - Handle errors\n\n**Properties:**\n- `method` - HTTP method\n- `headers` - Request headers\n- `query_params` - Query parameters\n- `body_text` - Request body as text\n- `body_json` - Request body as JSON\n- `path` - Request path\n- `url` - Request URL\n- `user_id` - Authenticated user ID\n- `is_authenticated` - Authentication status\n\n## Contributing\n\nContributions are welcome! Please submit pull requests or open issues for suggestions.\n\n## License\n\nThis package is distributed under the BSD-3-Clause License.\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "A lightweight, modular, and secure framework designed for building RESTful APIs in Appwrite Functions. It provides a streamlined development experience with built-in utilities for request handling, validation, authentication, and database interactions.",
"version": "2.0.1",
"project_urls": {
"Homepage": "https://github.com/mj-963/secure_api_py",
"Issues": "https://github.com/mj-963/secure_api_py/issues",
"Repository": "https://github.com/mj-963/secure_api_py"
},
"split_keywords": [
"appwrite",
" api",
" rest",
" framework",
" functions"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "0136bef140952955599e9e0708f3c13948bb5bad0ac5546f6d51ee9ca24b6761",
"md5": "39aaa12b628a27e7e60472fbe559ccd0",
"sha256": "f6e018e5c085f89e3c0c4f9085e3a5fecdf02bce02d832f6509f519069367356"
},
"downloads": -1,
"filename": "secure_api_py-2.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "39aaa12b628a27e7e60472fbe559ccd0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 23205,
"upload_time": "2025-11-09T16:17:21",
"upload_time_iso_8601": "2025-11-09T16:17:21.481043Z",
"url": "https://files.pythonhosted.org/packages/01/36/bef140952955599e9e0708f3c13948bb5bad0ac5546f6d51ee9ca24b6761/secure_api_py-2.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "45615ca25c2d2069ea0cbf437217fbb65391fe7c0778b7734fd4b552f3e10b63",
"md5": "66cd70007389c0b67c6107839db3c966",
"sha256": "eae2553735a0dda23df4ada9b1199287f9ab4be01e07bb6cb2125ffcc5bbae05"
},
"downloads": -1,
"filename": "secure_api_py-2.0.1.tar.gz",
"has_sig": false,
"md5_digest": "66cd70007389c0b67c6107839db3c966",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 24763,
"upload_time": "2025-11-09T16:17:23",
"upload_time_iso_8601": "2025-11-09T16:17:23.476542Z",
"url": "https://files.pythonhosted.org/packages/45/61/5ca25c2d2069ea0cbf437217fbb65391fe7c0778b7734fd4b552f3e10b63/secure_api_py-2.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-09 16:17:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mj-963",
"github_project": "secure_api_py",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "secure-api-py"
}