Skip to content

WIP cli tool #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
aa5ae3f
WIP cli
tbarbugli Jun 24, 2024
27db1ba
wip reflection based generated commands
sachaarbonel Jun 25, 2024
4f3e0b6
remove redudant click.echo in favour of print_result
sachaarbonel Jun 25, 2024
7e82ab0
Merge branch 'main' into cli
sachaarbonel Jun 25, 2024
79c073f
ruff fix
sachaarbonel Jun 25, 2024
ca3b403
fix test setup
sachaarbonel Jun 25, 2024
3d9d324
ruff fix
sachaarbonel Jun 25, 2024
853defa
handle --data
sachaarbonel Jun 25, 2024
a435f97
review: add better names
sachaarbonel Jun 25, 2024
a09ddce
more unit tests
sachaarbonel Jun 25, 2024
358c13e
test get or create
sachaarbonel Jul 3, 2024
cdb0115
more tests
sachaarbonel Jul 3, 2024
b61ec3c
docstrings
sachaarbonel Jul 3, 2024
eeb5095
more docstrings
sachaarbonel Jul 3, 2024
57170a4
dash - instead of underscore _
sachaarbonel Jul 3, 2024
809a218
more call commands
sachaarbonel Jul 3, 2024
543cfc9
test_cli_create_call_with_members
sachaarbonel Jul 3, 2024
33f80ff
mock_setup refactor to make tests more readable
sachaarbonel Jul 3, 2024
12f92e6
more tests
sachaarbonel Jul 3, 2024
be9adf1
tests tests tests
sachaarbonel Jul 3, 2024
8155403
ruff fix
sachaarbonel Jul 3, 2024
e1f5ad9
lint
sachaarbonel Jul 3, 2024
e25d9b3
rtmp input
tbarbugli Jul 3, 2024
159e42a
Merge branch 'cli' of github.com:GetStream/stream-py into cli
tbarbugli Jul 3, 2024
683314c
fix send-call-event cli
sachaarbonel Jul 4, 2024
9fd9e6a
makefile wip
sachaarbonel Jul 4, 2024
85219e8
makefile
sachaarbonel Jul 4, 2024
4062bdc
Dockerfile + makefile commands
sachaarbonel Jul 4, 2024
c296584
update readme
sachaarbonel Jul 4, 2024
7cab37a
rename to stream-cli
sachaarbonel Jul 5, 2024
caa764f
fix make command
sachaarbonel Jul 5, 2024
326f8ca
remove this log
sachaarbonel Jul 5, 2024
f45013b
completion + optional python-dotenv
sachaarbonel Jul 5, 2024
dfd00a9
poetry update
sachaarbonel Jul 5, 2024
cfdd3f7
update readme
sachaarbonel Jul 5, 2024
f6e049f
revert py dotenv change to prepare for config
sachaarbonel Jul 5, 2024
1c7f41e
config
sachaarbonel Jul 5, 2024
b6e7e2e
fix configure + completion install command
sachaarbonel Jul 5, 2024
dc2ad0d
improve instructions
sachaarbonel Jul 5, 2024
a7ba61a
stream-cli instructions
sachaarbonel Jul 5, 2024
3e1cd13
bring back support for env variables
sachaarbonel Jul 5, 2024
8254657
fix lock file
sachaarbonel Jul 5, 2024
2eea290
fix lints
sachaarbonel Jul 8, 2024
b2775c2
ending calls
tbarbugli Jul 9, 2024
0eaf9aa
Merge branch 'main' into cli
tbarbugli Sep 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use an official Python runtime as a parent image
FROM python:3.9-slim

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install poetry
RUN pip install poetry

# Install project dependencies
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi

# Copy the entrypoint script into the container
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Set the entrypoint script to be executed
ENTRYPOINT ["/entrypoint.sh"]

# Default command, if no command is provided when running the container
CMD ["--help"]
113 changes: 113 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Python interpreter
PYTHON := python3

# Poetry
POETRY := poetry

# pipx
PIPX := pipx

# Virtual environment
VENV := .venv

# Source directory
SRC_DIR := getstream

# Test directory
TEST_DIR := tests

# Project name (assuming it's the same as the directory name)
PROJECT_NAME := getstream

# Default target
.DEFAULT_GOAL := help

# Docker image name
IMAGE_NAME := getstream-cli

# GitHub Container Registry
GHCR_REPO := ghcr.io/$(shell echo ${GITHUB_REPOSITORY} | tr '[:upper:]' '[:lower:]')

.PHONY: help
help:
@echo "Available commands:"
@echo " install : Install project dependencies"
@echo " update : Update project dependencies"
@echo " test : Run tests"
@echo " lint : Run linter"
@echo " fix : Auto-fix linter issues"
@echo " format : Format code"
@echo " clean : Remove build artifacts and cache files"
@echo " run : Run the CLI application"
@echo " pipx-install: Install the project globally using pipx"
@echo " pipx-uninstall: Uninstall the project from pipx"
@echo " build : Build the project"
@echo " publish : Publish the project to PyPI"
@echo " docker-build : Build Docker image"
@echo " docker-run : Run Docker container (use CMD='command' to specify CLI command)"
@echo " docker-push : Push Docker image to GitHub Container Registry"

.PHONY: install
install:
$(POETRY) install

.PHONY: update
update:
$(POETRY) update

.PHONY: test
test:
$(POETRY) run pytest $(TEST_DIR)

.PHONY: lint
lint:
$(POETRY) run ruff check $(SRC_DIR) $(TEST_DIR)

.PHONY: fix
fix:
$(POETRY) run ruff check --fix $(SRC_DIR) $(TEST_DIR)

.PHONY: format
format:
$(POETRY) run ruff format $(SRC_DIR) $(TEST_DIR)

.PHONY: clean
clean:
find . -type d -name "__pycache__" -exec rm -rf {} +
find . -type f -name "*.py[co]" -delete
find . -type d -name ".pytest_cache" -exec rm -rf {} +
find . -type d -name ".ruff_cache" -exec rm -rf {} +
rm -rf build dist *.egg-info

.PHONY: run
run:
$(POETRY) run stream-cli $(ARGS)

.PHONY: pipx-install
pipx-install:
$(PIPX) install --editable .

.PHONY: pipx-uninstall
pipx-uninstall:
$(PIPX) uninstall $(PROJECT_NAME)

.PHONY: build
build:
$(POETRY) build

.PHONY: publish
publish:
$(POETRY) publish

.PHONY: docker-build
docker-build:
docker build -t $(IMAGE_NAME) .

.PHONY: docker-run
docker-run:
docker run -e STREAM_API_KEY=$(STREAM_API_KEY) -e STREAM_API_SECRET=$(STREAM_API_SECRET) $(IMAGE_NAME) $(CMD)

.PHONY: docker-push
docker-push:
docker tag $(IMAGE_NAME) $(GHCR_REPO):$(VERSION)
docker push $(GHCR_REPO):$(VERSION)
126 changes: 121 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,68 @@
- Video call creation and management
- Chat session creation and management
- Token generation for user authentication
- Command-line interface (CLI) for easy interaction
- Docker support for containerized usage

## Installation

To install the Stream Client Library, run the following command:
You can install the Stream Client Library using pip or pipx.

### Using pip

To install using pip, run the following command:

```sh
pip install getstream
```

### Using pipx

For a more isolated and manageable installation, especially for CLI tools, we recommend using pipx. Pipx installs the package in its own virtual environment, making it available globally while keeping it isolated from other Python packages.

First, install pipx if you haven't already:

```sh
python -m pip install --user pipx
python -m pipx ensurepath
```

Then, install the Stream Client Library using pipx:

```sh
pipx install getstream
```

To uninstall the package, run:

```sh
pipx uninstall getstream
```

This will make the `getstream` CLI command available globally on your system.

> [!NOTE]
> Using pipx is particularly beneficial for the CLI functionality of the Stream SDK. It ensures that the CLI is always available without affecting your other Python projects or global Python environment.

After installation with pipx, you can run CLI commands directly:

```sh
stream-cli create-token --user-id your_user_id
```

### Configuration and Completion

Your Stream CLI configuration and completion scripts are stored in `~/.stream-cli/`.

To set up:

1. Run `stream-cli configure` to set up your configuration.
2. Install completion for your shell:`stream-cli install-completion --shell bash # or zsh, or fish`
3. Add the suggested line to your shell's RC file (e.g., ~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish).
4. Restart your shell or source the RC file.

For library usage in your Python projects, the standard pip installation is recommended.

## Usage

To get started, you need to import the `Stream` class from the library and create a new instance with your API key and secret:
Expand Down Expand Up @@ -76,7 +129,6 @@ call.get_or_create(
# Chat: update settings for a channel type
```


### Chat API - Channels

To work with chat sessions, use the `client.chat` object and implement the desired chat methods in the `Chat` class:
Expand All @@ -87,6 +139,58 @@ chat_instance = client.chat
# TODO: implement and call chat-related methods with chat_instance
```

## Command-Line Interface (CLI)

The Stream SDK includes a CLI for easy interaction with the API. You can use it to perform various operations such as creating tokens, managing video calls, and more.

To use the CLI, run:

```sh
python -m getstream.cli [command] [options]
```

For example, to create a token:

```sh
python -m getstream.cli create-token --user-id your_user_id
```

For more information on available commands, run:

```sh
python -m getstream.cli --help
```

## Docker Support

The Stream SDK can be run in a Docker container. This is useful for deployment and consistent development environments.

### Building the Docker Image

To build the Docker image, run:

```sh
make docker-build
```

### Running Commands in Docker

To run a CLI command using Docker:

```sh
make docker-run CMD='create-token --user-id your_user_id'
```

Make sure to set the `STREAM_API_KEY` and `STREAM_API_SECRET` environment variables when running Docker commands.

### Pushing the Docker Image

To push the Docker image to the GitHub Container Registry (usually done by CI):

```sh
make docker-push VERSION=1.0.0
```

## Development

We use poetry to manage dependencies and run tests. It's a package manager for Python that allows you to declare the libraries your project depends on and manage them.
Expand All @@ -105,15 +209,27 @@ poetry shell

To run tests, create a `.env` using the `.env.example` and adjust it to have valid API credentials
```sh
poetry run pytest tests/ getstream/
make test
```

Before pushing changes make sure to have git hooks installed correctly, so that you get linting done locally `pre-commit install`

You can also run the code formatting yourself if needed:

```sh
poetry run ruff format getstream/ tests/
make format
```

To run the linter:

```sh
make lint
```

To fix linter issues automatically:

```sh
make fix
```

### Writing new tests
Expand All @@ -133,4 +249,4 @@ This project is licensed under the [MIT License](LICENSE).

## Contributing

Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) to get started.
Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) to get started.
10 changes: 10 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# Check if required environment variables are set
if [[ -z "${STREAM_API_KEY}" || -z "${STREAM_API_SECRET}" ]]; then
echo "Error: STREAM_API_KEY and STREAM_API_SECRET must be set"
exit 1
fi

# Run the CLI command with all passed arguments
poetry run python -m getstream.cli "$@"
66 changes: 66 additions & 0 deletions getstream/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import click
from typing import Optional
from getstream import Stream
from getstream.cli.completion import install_completion_command
from getstream.cli.configure import configure, get_credentials, show_config
from getstream.cli.utils import pass_client
from getstream.cli.video import video
from getstream.stream import BASE_URL

@click.group()
@click.option("--profile", default='default', help="Configuration profile to use")
@click.option("--base-url", default=BASE_URL, show_default=True)
@click.option("--timeout", default=3.0, show_default=True)
@click.pass_context
def cli(ctx, profile, base_url, timeout):
ctx.ensure_object(dict)

if ctx.invoked_subcommand == 'configure':
return # Skip credential check for 'configure' command

api_key, api_secret, app_name = get_credentials(profile)
if api_key is None or api_secret is None:
click.echo(f"Error: Unable to load credentials for profile '{profile}'.")
click.echo("Please run 'stream-cli configure' to set up your profile.")
ctx.exit(1)
ctx.obj["client"] = Stream(
api_key=api_key, api_secret=api_secret, timeout=timeout, base_url=base_url
)
ctx.obj["app_name"] = app_name

@click.command()
@click.option("--user-id", required=True)
@click.option("--call-cid", multiple=True, default=None)
@click.option("--role", default=None)
@click.option("--exp-seconds", type=int, default=None)
@pass_client
def create_token(
client: Stream,
app_name: str,
user_id: str,
call_cid=None,
role: Optional[str] = None,
exp_seconds=None,
):
if call_cid is not None and len(call_cid) > 0:
print(
client.create_call_token(
user_id=user_id, call_cids=call_cid, role=role, expiration=exp_seconds
)
)
else:
print(client.create_call_token(user_id=user_id))

cli.add_command(install_completion_command())
# cli.add_command(debug_config)
# cli.add_command(debug_permissions)
cli.add_command(configure)
cli.add_command(show_config)
cli.add_command(create_token)
cli.add_command(video) # Add video command directly to the main CLI group

def main():
cli(obj={})

if __name__ == "__main__":
main()
Loading
Loading