Metadata-Version: 2.5
Name: hotcodepush
Version: 0.1.0
Summary: The typed Python client for the HotCodePush REST API
Project-URL: Homepage, https://hotcodepush.com
Project-URL: Documentation, https://hotcodepush.com/docs/api/python
Project-URL: Repository, https://github.com/hotcodepush-team/hotcodepush-python
Project-URL: API Reference, https://api.hotcodepush.com/openapi
Author-email: HotCodePush <support@hotcodepush.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,capacitor,cordova,expo,hotcodepush,ota,over-the-air,react-native,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.28
Requires-Dist: pydantic<3,>=2.6
Description-Content-Type: text/markdown

# hotcodepush

[![PyPI](https://img.shields.io/pypi/v/hotcodepush)](https://pypi.org/project/hotcodepush/)

The typed Python client for the [HotCodePush](https://hotcodepush.com) REST API, the over-the-air (OTA) update platform for React Native, Expo, Capacitor and Cordova.

## Installation

The package is not on PyPI yet, so install a commit of `main` by its SHA:

```sh
pip install git+https://github.com/hotcodepush-team/hotcodepush-python@<sha>
```

Or with uv:

```sh
uv add git+https://github.com/hotcodepush-team/hotcodepush-python@<sha>
```

Pin a commit and bump it on purpose, never `@main`.

It requires Python 3.11 or later.

## Usage

```python
from hotcodepush import HotCodePush

hot_code_push = HotCodePush()  # reads the API token from HOTCODEPUSH_TOKEN

organization, *_ = hot_code_push.organizations.list()
app = hot_code_push.organizations.apps.create(
    framework="capacitor", name="Demo", organization_id=organization.id
)
channel = hot_code_push.apps.channels.create(app_id=app.id, name="staging")
hot_code_push.apps.channels.pause(app_id=app.id, channel_id=channel.id)
```

The resources mirror the API's paths, `/v1/apps/{appId}/channels` being `apps.channels`.
Every method takes keyword arguments and returns pydantic models with snake_case fields.
An optional argument you leave out stays out of the request; `None` sends `null`, which clears a field such as a channel's `expires_at`.
`users.get(user_id="me")` answers the caller behind the token, as `me` addresses the caller wherever the API takes a `{userId}`.

An upload takes `bytes` or a file object with its `content_length`, and streams it.
Bytes above 64 MiB go up in parts, and a retry sends them again; a file object is read once, so a failed upload of one is not retried.

Creating an organization, an invitation, an app, a channel, a release, a rollback, a bundle or a binary sends an `Idempotency-Key`, a UUID per call kept across the client's own retries; pass `idempotency_key` to reuse one when you retry the call yourself, and the API answers the first result again for 24 hours.

A failed request raises a `HotCodePushError` with the API's `code`, `message` and `details` and the HTTP `status`.

## Documentation

The documentation lives at [hotcodepush.com/docs/api/python](https://hotcodepush.com/docs/api/python).

## Development

```sh
uv sync
uv run ruff format --check .
uv run ruff check .
uv run mypy
uv run pytest
uv build
```

`uv run ruff format .` formats the code.

## License

See [LICENSE](./LICENSE).
