Simple SDK for Heroku AppLink and Salesforce development
Project description
Python SDK for Heroku AppLink
This library provides basic functionality for building Python apps that use Heroku AppLink to secure communication and credential sharing with a Salesforce org.
Though the interaction with AppLink is simple and easy to hand code, using the SDK will quickstart your project experience.
Use of this project with Salesforce is subject to the TERMS_OF_USE.md document.
Documentation for the SDK is available and is generated from the source code.
Generate Documentation
Install the doc dependency group.
$ uv sync --group docs
Generate the documentation.
$ uv run pdoc3 --template-dir templates/python heroku_applink -o docs --force
Development
Setting Up the Development Environment
-
Clone the repository:
git clone https://github.com/heroku/heroku-applink-python.git cd heroku-applink-python
-
Install Dependencies:
Install the
uvpackage manager:curl -LsSf https://astral.sh/uv/install.sh | sh
Sync all dependencies:
uv sync --all-extras
-
Sync Development Dependencies:
uv sync --all-extras --dev
Running Tests
-
Run the full test suite:
# Run all tests uv run pytest # Run all tests with coverage uv run pytest --cov=heroku_applink.data_api --cov-report=term-missing -v
-
Run a single test:
# Run a specific test file uv run pytest <path_to_test_file>/test_specific_file.py # Run a specific test file with coverage uv run pytest tests/data_api/test_data_api_record.py::test_some_specific_case \ --cov=heroku_applink.data_api
-
Run tests with a specific Python version:
pyenv shell 3.12.2 # Or any installed version uv venv source .venv/bin/activate uv sync --all-extras --dev uv run pytest
-
Run tests across multiple Python versions with Tox:
uv sync --all-extras --dev uv run tox
Linting and Code Quality
-
Run the Ruff linter:
# Check the code for issues uv run ruff check . # Automatically fix issues uv run ruff check . --fix # Check a specific directory (e.g., heroku_applink) uv run ruff check heroku_applink/ # Format the codebase uv run ruff format .
Usage Examples
For more detailed information about the SDK's capabilities, please refer to the full documentation.
Basic Setup
Install the package.
$ uv pip install heroku_applink
ASGI
If you are using an ASGI framework (like FastAPI), you can use the IntegrationAsgiMiddleware to automatically populate the client-context in the request scope.
# FastAPI example
import asyncio
import heroku_applink as sdk
from fastapi import FastAPI
config = sdk.Config(request_timeout=5)
app = FastAPI()
app.add_middleware(sdk.IntegrationAsgiMiddleware, config=config)
@app.get("/")
def get_root():
return {"root": "page"}
@app.get("/accounts")
async def get_accounts():
data_api = sdk.get_client_context().data_api
result = await query_accounts(data_api)
accounts = [
{
"id": record.fields["Id"],
"name": record.fields["Name"]
}
for record in result.records
]
return accounts
async def query_accounts(data_api):
query = "SELECT Id, Name FROM Account"
result = await data_api.query(query)
for record in result.records:
print("===== account record", record)
return result
WSGI
If you are using a WSGI framework (like Flask), you can use the IntegrationWsgiMiddleware to automatically populate the client-context in the request environment.
from flask import Flask, jsonify, request
import heroku_applink as sdk
config = sdk.Config(request_timeout=5)
app = Flask(__name__)
app.wsgi_app = sdk.IntegrationWsgiMiddleware(app.wsgi_app, config=config)
@app.route("/")
def index():
return jsonify({"message": "Hello, World!"})
@app.route("/accounts")
def get_accounts():
data_api = sdk.get_client_context().data_api
query = "SELECT Id, Name FROM Account"
result = data_api.query(query)
return jsonify({"accounts": [record.get("Name") for record in result.records]})
Directly from the x-client-context header
If you are not using a framework, you can manually extract the x-client-context
header and use the DataAPI class to query the Salesforce org.
from heroku_applink.data_api import DataAPI
header = request.headers.get("x-client-context")
decoded = base64.b64decode(header)
data = json.loads(decoded)
data_api = DataAPI(
org_domain_url=data["orgDomainUrl"],
api_version=data["apiVersion"],
access_token=data["accessToken"],
)
result = data_api.query("SELECT Id, Name FROM Account")
Directly using the get_authorization function
import asyncio
import heroku_applink as sdk
async def main():
# Get authorization for a developer
authorization = await sdk.get_authorization(
developer_name="your_developer_name",
attachment_or_url="HEROKU_APPLINK"
)
# Access the context properties
print(f"Organization ID: {authorization.org.id}")
print(f"User ID: {authorization.org.user.id}")
print(f"Username: {authorization.org.user.username}")
# Use the DataAPI to make queries
query = "SELECT Id, Name FROM Account"
result = await authorization.data_api.query(query)
for record in result.records:
print(f"Account: {record}")
# Run the async function
asyncio.run(main())
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file heroku_applink-1.1.4.tar.gz.
File metadata
- Download URL: heroku_applink-1.1.4.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7f0971b452cc7bac7290a06da7142d4a2903e3aacc607915124f324734e5355
|
|
| MD5 |
c7ceab4afea4a760e6b88b92151494d2
|
|
| BLAKE2b-256 |
f8971fa1c84b795a089031dcdbeb113190d13cd11f21ec50305471ed1ab3b7a4
|
File details
Details for the file heroku_applink-1.1.4-py3-none-any.whl.
File metadata
- Download URL: heroku_applink-1.1.4-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
762e00f364ca7321490faef0ba9c31ef4d9ef291f415a6eb45172c7d684f5ec1
|
|
| MD5 |
34ca173bb24dfabc9c9384fa475e7b2e
|
|
| BLAKE2b-256 |
c29a3f6f5686f4183a69e50f927b08c678caae6bfdcdc53d26a1d35a05c3225a
|