Skip to content

Commit 0d51bd8

Browse files
authored
Merge branch 'main' into fix/predict-numpy-images
2 parents 18a3ae8 + c570d22 commit 0d51bd8

File tree

39 files changed

+1553
-410
lines changed

39 files changed

+1553
-410
lines changed

.github/workflows/publish.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,35 @@ jobs:
3030
PYPI_TEST_PASSWORD: ${{ secrets.PYPI_TEST_PASSWORD }}
3131
run: |
3232
make publish -e PYPI_USERNAME=$PYPI_USERNAME -e PYPI_PASSWORD=$PYPI_PASSWORD -e PYPI_TEST_PASSWORD=$PYPI_TEST_PASSWORD
33+
34+
deploy-docs:
35+
needs: build
36+
runs-on: ubuntu-latest
37+
permissions:
38+
contents: write
39+
steps:
40+
- name: 🛎️ Checkout
41+
uses: actions/checkout@v4
42+
with:
43+
fetch-depth: 0
44+
45+
- name: 🐍 Set up Python
46+
uses: actions/setup-python@v5
47+
with:
48+
python-version: '3.8'
49+
50+
- name: 📚 Install MkDocs and dependencies
51+
run: |
52+
python -m pip install --upgrade pip
53+
pip install mkdocs-material mkdocstrings mkdocstrings[python]
54+
pip install ".[dev]"
55+
56+
- name: 🏗️ Build documentation
57+
run: |
58+
mkdocs build
59+
60+
- name: 🚀 Deploy to GitHub Pages
61+
uses: peaceiris/actions-gh-pages@v3
62+
with:
63+
github_token: ${{ secrets.GITHUB_TOKEN }}
64+
publish_dir: ./site

.github/workflows/test.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ on:
88

99
jobs:
1010
build:
11-
runs-on: ubuntu-latest
1211
strategy:
1312
matrix:
14-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
13+
os: ["ubuntu-latest", "windows-latest"]
14+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
15+
runs-on: ${{ matrix.os }}
16+
env:
17+
PYTHONUTF8: 1
1518

1619
steps:
1720
- name: 🛎️ Checkout

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,4 @@ tests/manual/data
154154
README.roboflow.txt
155155
*.zip
156156
.DS_Store
157+
.claude

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ci:
66

77
repos:
88
- repo: https://github.com/pre-commit/pre-commit-hooks
9-
rev: v4.6.0
9+
rev: v5.0.0
1010
hooks:
1111
- id: check-added-large-files
1212
- id: check-case-conflict
@@ -24,14 +24,14 @@ repos:
2424
- id: trailing-whitespace
2525

2626
- repo: https://github.com/PyCQA/bandit
27-
rev: 1.7.9
27+
rev: 1.8.3
2828
hooks:
2929
- id: bandit
3030
args: ["-c", "pyproject.toml"]
3131
additional_dependencies: ["bandit[toml]"]
3232

3333
- repo: https://github.com/astral-sh/ruff-pre-commit
34-
rev: v0.6.4
34+
rev: v0.11.12
3535
hooks:
3636
- id: ruff-format
3737
- id: ruff

CLAUDE.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Development Commands
6+
7+
### Running Tests
8+
```bash
9+
python -m unittest
10+
```
11+
12+
### Linting and Code Quality
13+
```bash
14+
# Format code with ruff
15+
make style
16+
17+
# Check code quality (includes ruff and mypy)
18+
make check_code_quality
19+
20+
# Individual commands
21+
ruff format roboflow
22+
ruff check roboflow --fix
23+
mypy roboflow
24+
```
25+
26+
### Building Documentation
27+
```bash
28+
# Install documentation dependencies
29+
python -m pip install mkdocs mkdocs-material mkdocstrings mkdocstrings[python]
30+
31+
# Serve documentation locally
32+
mkdocs serve
33+
```
34+
35+
### Installing Development Environment
36+
```bash
37+
# Create virtual environment
38+
python3 -m venv env
39+
source env/bin/activate
40+
41+
# Install in editable mode with dev dependencies
42+
pip install -e ".[dev]"
43+
44+
# Install pre-commit hooks
45+
pip install pre-commit
46+
pre-commit install
47+
```
48+
49+
## Architecture Overview
50+
51+
The Roboflow Python SDK follows a hierarchical object model that mirrors the Roboflow platform structure:
52+
53+
### Core Components
54+
55+
1. **Roboflow** (`roboflow/__init__.py`) - Entry point and authentication
56+
- Handles API key management and workspace initialization
57+
- Provides `login()` for CLI authentication
58+
- Creates workspace connections
59+
60+
2. **Workspace** (`roboflow/core/workspace.py`) - Manages Roboflow workspaces
61+
- Lists and accesses projects
62+
- Handles dataset uploads and model deployments
63+
- Manages workspace-level operations
64+
65+
3. **Project** (`roboflow/core/project.py`) - Represents a computer vision project
66+
- Manages project metadata and versions
67+
- Handles image/annotation uploads
68+
- Supports different project types (object-detection, classification, etc.)
69+
70+
4. **Version** (`roboflow/core/version.py`) - Dataset version management
71+
- Downloads datasets in various formats
72+
- Deploys models
73+
- Provides access to trained models for inference
74+
75+
5. **Model Classes** (`roboflow/models/`) - Type-specific inference models
76+
- `ObjectDetectionModel` - Bounding box predictions
77+
- `ClassificationModel` - Image classification
78+
- `InstanceSegmentationModel` - Pixel-level segmentation
79+
- `SemanticSegmentationModel` - Class-based segmentation
80+
- `KeypointDetectionModel` - Keypoint predictions
81+
82+
### API Adapters
83+
84+
- **rfapi** (`roboflow/adapters/rfapi.py`) - Low-level API communication
85+
- **deploymentapi** (`roboflow/adapters/deploymentapi.py`) - Model deployment operations
86+
87+
### CLI Interface
88+
89+
The `roboflow` command line tool (`roboflow/roboflowpy.py`) provides:
90+
- Authentication: `roboflow login`
91+
- Dataset operations: `roboflow download`, `roboflow upload`, `roboflow import`
92+
- Inference: `roboflow infer`
93+
- Project/workspace management: `roboflow project`, `roboflow workspace`
94+
95+
### Key Design Patterns
96+
97+
1. **Hierarchical Access**: Always access objects through their parent (Workspace → Project → Version → Model)
98+
2. **API Key Flow**: API key is passed down through the object hierarchy
99+
3. **Format Flexibility**: Supports multiple dataset formats (YOLO, COCO, Pascal VOC, etc.)
100+
4. **Batch Operations**: Upload and download operations support concurrent processing
101+
102+
## Project Configuration
103+
104+
- **Python Version**: 3.8+
105+
- **Main Dependencies**: See `requirements.txt`
106+
- **Entry Point**: `roboflow=roboflow.roboflowpy:main`
107+
- **Code Style**: Enforced by ruff with Google docstring convention
108+
- **Type Checking**: mypy configured for Python 3.8
109+
110+
## Important Notes
111+
112+
- API keys are stored in `~/.config/roboflow/config.json` (Unix) or `~/roboflow/config.json` (Windows)
113+
- The SDK supports both hosted inference (Roboflow platform) and local inference (via Roboflow Inference)
114+
- Pre-commit hooks automatically run formatting and linting checks
115+
- Test files intentionally excluded from linting: `tests/manual/debugme.py`

Dockerfile.dev

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
FROM python:3.8
2-
RUN apt-get update && apt-get install -y make libgl1-mesa-glx && rm -rf /var/lib/apt/lists/*
1+
FROM python:3.10
2+
RUN apt-get update && apt-get install -y make curl libgl1-mesa-glx && rm -rf /var/lib/apt/lists/*
3+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
4+
ENV PATH="/root/.local/bin:${PATH}"
5+
36
WORKDIR /roboflow-python
47
COPY .devcontainer/bashrc_ext /root/bashrc_ext
58
RUN echo "source /root/bashrc_ext" >> ~/.bashrc
6-
COPY ./setup.py ./pyproject.toml ./README.md ./requirements.txt ./
9+
10+
COPY ./requirements.txt ./
11+
RUN uv pip install --system -r requirements.txt
12+
13+
COPY ./setup.py ./pyproject.toml ./README.md ./
714
COPY roboflow/__init__.py ./roboflow/__init__.py
8-
RUN pip install -e ".[dev]"
15+
RUN uv pip install --system -e ".[dev]"
16+
917
COPY . .

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ matplotlib
66
numpy>=1.18.5
77
opencv-python-headless==4.10.0.84
88
Pillow>=7.1.2
9+
pillow-heif>=0.18.0
910
python-dateutil
1011
python-dotenv
1112
requests

roboflow/__init__.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from roboflow.models import CLIPModel, GazeModel # noqa: F401
1616
from roboflow.util.general import write_line
1717

18-
__version__ = "1.1.50"
18+
__version__ = "1.1.65"
1919

2020

2121
def check_key(api_key, model, notebook, num_retries=0):
@@ -43,7 +43,7 @@ def check_key(api_key, model, notebook, num_retries=0):
4343
num_retries += 1
4444
return check_key(api_key, model, notebook, num_retries)
4545
else:
46-
raise RuntimeError("There was an error validating the api key with Roboflow" " server.")
46+
raise RuntimeError("There was an error validating the api key with Roboflow server.")
4747
else:
4848
r = response.json()
4949
return r
@@ -71,7 +71,7 @@ def login(workspace=None, force=False):
7171
# default configuration location
7272
conf_location = os.getenv("ROBOFLOW_CONFIG_DIR", default=default_path)
7373
if os.path.isfile(conf_location) and not force:
74-
write_line("You are already logged into Roboflow. To make a different login," "run roboflow.login(force=True).")
74+
write_line("You are already logged into Roboflow. To make a different login,run roboflow.login(force=True).")
7575
return None
7676
# we could eventually return the workspace object here
7777
# return Roboflow().workspace()
@@ -131,17 +131,12 @@ def initialize_roboflow(the_workspace=None):
131131

132132
global active_workspace
133133

134-
conf_location = os.getenv("ROBOFLOW_CONFIG_DIR", default=str(Path.home() / ".config" / "roboflow" / "config.json"))
135-
136-
if not os.path.isfile(conf_location):
137-
raise RuntimeError("To use this method, you must first login - run roboflow.login()")
134+
if the_workspace is None:
135+
active_workspace = Roboflow().workspace()
138136
else:
139-
if the_workspace is None:
140-
active_workspace = Roboflow().workspace()
141-
else:
142-
active_workspace = Roboflow().workspace(the_workspace)
137+
active_workspace = Roboflow().workspace(the_workspace)
143138

144-
return active_workspace
139+
return active_workspace
145140

146141

147142
def load_model(model_url):

roboflow/adapters/deploymentapi.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ class DeploymentApiError(Exception):
99
pass
1010

1111

12-
def add_deployment(api_key, machine_type, duration, delete_on_expiration, deployment_name, inference_version):
12+
def add_deployment(
13+
api_key, creator_email, machine_type, duration, delete_on_expiration, deployment_name, inference_version
14+
):
1315
url = f"{DEDICATED_DEPLOYMENT_URL}/add"
1416
params = {
1517
"api_key": api_key,
18+
"creator_email": creator_email,
1619
# "security_level": security_level,
1720
"duration": duration,
1821
"delete_on_expiration": delete_on_expiration,
@@ -69,6 +72,22 @@ def get_deployment_usage(api_key, deployment_name, from_timestamp, to_timestamp)
6972
return response.status_code, response.json()
7073

7174

75+
def pause_deployment(api_key, deployment_name):
76+
url = f"{DEDICATED_DEPLOYMENT_URL}/pause"
77+
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})
78+
if response.status_code != 200:
79+
return response.status_code, response.text
80+
return response.status_code, response.json()
81+
82+
83+
def resume_deployment(api_key, deployment_name):
84+
url = f"{DEDICATED_DEPLOYMENT_URL}/resume"
85+
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})
86+
if response.status_code != 200:
87+
return response.status_code, response.text
88+
return response.status_code, response.json()
89+
90+
7291
def delete_deployment(api_key, deployment_name):
7392
url = f"{DEDICATED_DEPLOYMENT_URL}/delete"
7493
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})

0 commit comments

Comments
 (0)