Metadata-Version: 2.4
Name: colab-share
Version: 1.1.0
Summary: Утилиты для туннелирования веб-интерфейсов в Google Colab
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.32.4
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-timeout; extra == "dev"
Dynamic: license-file

# colab-share

Библиотека для публичного туннелирования локальных портов в Google Colab.
Поддерживает в настоящий момент 15 провайдеров, работает молча — выдаёт ссылку без лишних действий со стороны пользователя.


```python
from colab_share import get_share_link
link = get_share_link('srvus', 7860)
print(link)
```

---

## Установка

```bash
uv pip install colab-share
```

```bash
pip install colab-share
```

```bash
uv add colab-share
```

---

## Быстрый старт

```python
from colab_share import get_share_link

# Один провайдер
link = get_share_link('gradio', 7860)

# Все провайдеры параллельно
links = get_share_link('all', 7860)
```

---

## Провайдеры

| Имя            | Старт | RTT    | Примечания                                 |
|----------------|-------|--------|--------------------------------------------|
| `srvus`        | ~0.4с | ~200мс | Один из быстрейших                         |
| `bore`         | ~0.5с | ~150мс | Минимальная задержка                       |
| `localt`       | ~0.3с | ~300мс |                                            |
| `localhostrun` | ~0.7с | ~200мс |                                            |
| `gradio`       | ~0.5с | ~200мс |                                            |
| `tmole`        | ~1.5с | ~350мс |                                            |
| `beeceptor`    | ~2с   | ~400мс |                                            |
| `optimistix`   | ~1.5с | ~500мс |                                            |
| `mmar`         | ~1с   | ~600мс |                                            |
| `serveo`       | ~1.5с | ~700мс |                                            |
| `boredigital`  | ~1.5с | ~900мс |                                            |
| `cloudflared`  | ~4с   | ~400мс | Warmup ~15с после старта                   |
| `tunnelite`    | ~4с   | ~300мс |                                            |
| `native`       | ~2с   | —      | Только в Colab, требует Google-авторизации |
| `tunwg`        | —     | —      | Отключён: сервис временно недоступен       |

SSH-провайдеры (`srvus`, `serveo`, `localhostrun`, `optimistix`) используют стандартный SSH-ключ системы, при необходимости генерируется автоматически.

---

## API

### `get_share_link(host, port)`

Получить публичную ссылку через указанный провайдер.

```python
from colab_share import get_share_link

link = get_share_link('gradio', 7860)
# host='all' — запустить всех параллельно, вернуть все ссылки
links = get_share_link('all', 7860)
```

---

### `try_all(port)`

Параллельно запускает всех активных провайдеров, возвращает все полученные ссылки.

```python
from colab_share import try_all

print(try_all(7860))
# gradio: https://...gradio.live
# bore: http://bore.pub:XXXXX/
# srvus: https://...srv.us
# ...
```

---

### `benchmark(providers, timeout_per_provider, latency_timeout, print_report)`

Последовательно тестирует провайдеров с замером времени старта и RTT.
Требует бинарник `test_server` из папки проекта.

```python
from colab_share import benchmark

results = benchmark()
# Бенчмарк: 14 провайдеров, порт XXXXX.
# [srvus       ] OK (0.43с). Проверка... RTT 174мс
# [bore        ] OK (0.81с). Проверка... RTT 125мс
# ...
# Итого: 14/14 провайдеров работают.
# Минимальная задержка: bore (125мс)

# Выборочно
results = benchmark(providers=['cloudflared', 'bore', 'gradio'])

# Результаты — список TunnelBenchmarkResult
for r in results:
    print(r.name, r.tunnel_time, r.latency, r.url)
```

Путь к `test_server` определяется автоматически:
1. Переменная окружения `TEST_SERVER_PATH`
2. `../test_server/test_server` относительно пакета
3. `./test_server/test_server` относительно CWD

---

### Управление провайдерами

```python
from colab_share import list_providers, disable_provider, enable_provider

# Статус всех провайдеров
list_providers()
# {'tmole': True, 'tunwg': False, 'cloudflared': True, ...}

# Отключить нерабочий
disable_provider('tunwg')

# Включить обратно
enable_provider('tunwg')
```

Отключённый провайдер не попадает в `get_share_link('all', ...)`, `try_all()` и `benchmark()`,
но его функция (`get_tunwg_url`) остаётся доступна напрямую.

---

### Утилиты

```python
from colab_share import download, run, WORK_FOLDER

# Скачать файл с прогрессом
path = download('https://example.com/file.tar.gz', save_path='/tmp')

# Выполнить shell-команду
result = run('echo hello', timeout=10)
print(result['status_code'], result['output'])

# Рабочая папка (по умолчанию /content/.config)
print(WORK_FOLDER)
```

---

## Конфигурация

| Переменная окружения | По умолчанию       | Описание                           |
|----------------------|--------------------|------------------------------------|
| `TUNNEL_WORK_DIR`    | `/content/.config` | Папка для бинарников и кэша        |
| `TEST_SERVER_PATH`   | —                  | Путь к бинарнику тестового сервера |

```python
import os
os.environ['TUNNEL_WORK_DIR'] = '/tmp/tunnels'

from colab_share import get_share_link  # подхватит новый путь
```

> **Важно:** переменная `TUNNEL_WORK_DIR` должна быть установлена **до** первого импорта `colab_share`.

---

## Добавление своего провайдера

```python
from colab_share import tunnel_provider, get_share_link

@tunnel_provider('myprovider')
def get_myprovider_url(port: int) -> str:
    # Запустить бинарник/SSH и вернуть публичный URL
    return 'https://...'

# Провайдер сразу доступен
link = get_share_link('myprovider', 7860)
```

Для провайдеров на основе бинарных утилит удобно использовать `get_revproxy_url`:

```python
from colab_share._tunnels import get_revproxy_url
from colab_share._config import WORK_FOLDER
from colab_share import tunnel_provider

@tunnel_provider('myprovider')
def get_myprovider_url(port: int) -> str:
    return get_revproxy_url(
        bin_url='https://example.com/mytunnel-linux-amd64',
        need_unpack=False,
        bin_path=WORK_FOLDER / 'mytunnel',
        start_commands=[str(WORK_FOLDER / 'mytunnel'), str(port)],
        read_from_stderr=False,
        url_pattern=r'https://\S+\.mytunnel\.io',
        timeout=20.0,
    )
```

---

## Разработка

```bash
git clone --depth 1 https://github.com/imbecility/colab-share
cd colab-share
pip install -e ".[dev]"

# Запустить тесты (не требуют сети)
pytest tests/

# Тесты регулярных выражений провайдеров
pytest tests/test_regex.py -v

# Тесты утилит (требуют Unix)
pytest tests/test_utils.py -v
```

### Структура проекта

```
colab_share/
├── __init__.py       # Публичный API
├── _config.py        # Пути и HTTP-заголовки
├── _logger.py        # Логгер (по умолчанию WARNING)
├── _registry.py      # Реестр провайдеров (@tunnel_provider)
├── _utils.py         # Утилиты: процессы, сеть, архивы
├── _tunnels.py       # Провайдеры на основе бинарников
├── _ssh.py           # SSH-провайдеры
└── _diagnostics.py   # Бенчмарк

tests/
├── test_regex.py     # Валидация regex-паттернов провайдеров
└── test_utils.py     # Тесты утилитарных функций
```

### Детальный лог

```python
import logging
logging.getLogger('colab_share').setLevel(logging.DEBUG)
```

---

## Лицензия

MIT
