durable_huggingface_hub 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +29 -0
- data/.rubocop.yml +108 -0
- data/CHANGELOG.md +127 -0
- data/README.md +547 -0
- data/Rakefile +106 -0
- data/devenv.lock +171 -0
- data/devenv.nix +15 -0
- data/devenv.yaml +8 -0
- data/huggingface_hub.gemspec +63 -0
- data/lib/durable_huggingface_hub/authentication.rb +245 -0
- data/lib/durable_huggingface_hub/cache.rb +508 -0
- data/lib/durable_huggingface_hub/configuration.rb +191 -0
- data/lib/durable_huggingface_hub/constants.rb +145 -0
- data/lib/durable_huggingface_hub/errors.rb +412 -0
- data/lib/durable_huggingface_hub/file_download.rb +831 -0
- data/lib/durable_huggingface_hub/hf_api.rb +1278 -0
- data/lib/durable_huggingface_hub/repo_card.rb +430 -0
- data/lib/durable_huggingface_hub/types/cache_info.rb +298 -0
- data/lib/durable_huggingface_hub/types/commit_info.rb +149 -0
- data/lib/durable_huggingface_hub/types/dataset_info.rb +158 -0
- data/lib/durable_huggingface_hub/types/model_info.rb +154 -0
- data/lib/durable_huggingface_hub/types/space_info.rb +158 -0
- data/lib/durable_huggingface_hub/types/user.rb +179 -0
- data/lib/durable_huggingface_hub/types.rb +205 -0
- data/lib/durable_huggingface_hub/utils/auth.rb +174 -0
- data/lib/durable_huggingface_hub/utils/headers.rb +220 -0
- data/lib/durable_huggingface_hub/utils/http.rb +329 -0
- data/lib/durable_huggingface_hub/utils/paths.rb +230 -0
- data/lib/durable_huggingface_hub/utils/progress.rb +217 -0
- data/lib/durable_huggingface_hub/utils/retry.rb +165 -0
- data/lib/durable_huggingface_hub/utils/validators.rb +236 -0
- data/lib/durable_huggingface_hub/version.rb +8 -0
- data/lib/huggingface_hub.rb +205 -0
- metadata +334 -0
data/README.md
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
# HuggingFace Hub Ruby
|
|
2
|
+
|
|
3
|
+
A pure Ruby implementation of the HuggingFace Hub client library. This library provides a complete, production-ready interface to HuggingFace Hub for downloading models, datasets, and managing repositories - with zero Python dependencies.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Pure Ruby Implementation**: No Python required - runs entirely in Ruby
|
|
8
|
+
- **Complete Hub API**: Download models, datasets, and manage repositories
|
|
9
|
+
- **Smart Caching**: ETag-based validation with symlink optimization for storage efficiency
|
|
10
|
+
- **Authentication**: Full token management with multiple authentication methods
|
|
11
|
+
- **Progress Tracking**: Built-in progress bars for uploads and downloads
|
|
12
|
+
- **Offline Mode**: Work with cached models when offline
|
|
13
|
+
- **Repository Management**: Create, delete, and manage Hub repositories
|
|
14
|
+
- **File Operations**: Upload, download, and delete files with LFS support
|
|
15
|
+
- **Model Cards**: Read and write model, dataset, and space cards
|
|
16
|
+
- **Production Ready**: Comprehensive error handling, retries, and logging
|
|
17
|
+
- **Type Safe**: Validation and type checking throughout
|
|
18
|
+
- **Well Documented**: Extensive API documentation and usage examples
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
require 'huggingface_hub'
|
|
24
|
+
|
|
25
|
+
# Download a file from a model repository
|
|
26
|
+
HuggingfaceHub.hf_hub_download(
|
|
27
|
+
repo_id: 'gpt2',
|
|
28
|
+
filename: 'config.json'
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Or use the API client directly
|
|
32
|
+
api = HuggingfaceHub::HfApi.new
|
|
33
|
+
models = api.list_models(filter: 'text-generation')
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
Add this line to your application's Gemfile:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
gem 'huggingface_hub'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
And then execute:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
bundle install
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or install it yourself as:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
gem install huggingface_hub
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Ruby 3.0 or higher
|
|
59
|
+
- No Python dependencies required
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Downloading Files
|
|
64
|
+
|
|
65
|
+
Download a specific file from a repository:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
require 'huggingface_hub'
|
|
69
|
+
|
|
70
|
+
# Download a model configuration file
|
|
71
|
+
config_path = HuggingfaceHub.hf_hub_download(
|
|
72
|
+
repo_id: 'bert-base-uncased',
|
|
73
|
+
filename: 'config.json'
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Download from a specific revision
|
|
77
|
+
model_path = HuggingfaceHub.hf_hub_download(
|
|
78
|
+
repo_id: 'gpt2',
|
|
79
|
+
filename: 'pytorch_model.bin',
|
|
80
|
+
revision: 'main'
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Download with authentication
|
|
84
|
+
private_file = HuggingfaceHub.hf_hub_download(
|
|
85
|
+
repo_id: 'private/model',
|
|
86
|
+
filename: 'model.safetensors',
|
|
87
|
+
token: ENV['HF_TOKEN']
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Downloading Entire Repositories
|
|
92
|
+
|
|
93
|
+
Download all files from a repository:
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
# Download entire model repository
|
|
97
|
+
local_dir = HuggingfaceHub.snapshot_download(
|
|
98
|
+
repo_id: 'gpt2',
|
|
99
|
+
revision: 'main'
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Download only specific file patterns
|
|
103
|
+
filtered_dir = HuggingfaceHub.snapshot_download(
|
|
104
|
+
repo_id: 'bert-base-uncased',
|
|
105
|
+
allow_patterns: ['*.json', '*.txt'],
|
|
106
|
+
ignore_patterns: ['*.bin']
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Authentication
|
|
111
|
+
|
|
112
|
+
Multiple ways to authenticate:
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Login interactively
|
|
116
|
+
HuggingfaceHub.login
|
|
117
|
+
|
|
118
|
+
# Login with token
|
|
119
|
+
HuggingfaceHub.login(token: 'hf_...')
|
|
120
|
+
|
|
121
|
+
# Use environment variable
|
|
122
|
+
ENV['HF_TOKEN'] = 'hf_...'
|
|
123
|
+
|
|
124
|
+
# Pass token directly to API calls
|
|
125
|
+
api = HuggingfaceHub::HfApi.new(token: 'hf_...')
|
|
126
|
+
|
|
127
|
+
# Check current user
|
|
128
|
+
user_info = api.whoami
|
|
129
|
+
puts "Logged in as: #{user_info['name']}"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Repository Management
|
|
133
|
+
|
|
134
|
+
Create and manage repositories:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
api = HuggingfaceHub::HfApi.new
|
|
138
|
+
|
|
139
|
+
# Create a new model repository
|
|
140
|
+
url = api.create_repo(
|
|
141
|
+
repo_id: 'my-awesome-model',
|
|
142
|
+
repo_type: 'model',
|
|
143
|
+
private: false
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Check if repository exists
|
|
147
|
+
exists = api.repo_exists(repo_id: 'my-awesome-model')
|
|
148
|
+
|
|
149
|
+
# Get repository information
|
|
150
|
+
info = api.model_info(repo_id: 'gpt2')
|
|
151
|
+
puts "Model tags: #{info.tags}"
|
|
152
|
+
puts "Last modified: #{info.last_modified}"
|
|
153
|
+
|
|
154
|
+
# Delete a repository
|
|
155
|
+
api.delete_repo(repo_id: 'my-test-model')
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### File Operations
|
|
159
|
+
|
|
160
|
+
Upload and manage files in repositories:
|
|
161
|
+
|
|
162
|
+
```ruby
|
|
163
|
+
api = HuggingfaceHub::HfApi.new
|
|
164
|
+
|
|
165
|
+
# Upload a single file
|
|
166
|
+
api.upload_file(
|
|
167
|
+
path_or_fileobj: './model.safetensors',
|
|
168
|
+
path_in_repo: 'model.safetensors',
|
|
169
|
+
repo_id: 'my-model'
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Upload an entire folder
|
|
173
|
+
api.upload_folder(
|
|
174
|
+
folder_path: './my-model',
|
|
175
|
+
repo_id: 'my-model',
|
|
176
|
+
commit_message: 'Upload complete model'
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Delete a file
|
|
180
|
+
api.delete_file(
|
|
181
|
+
path_in_repo: 'old_model.bin',
|
|
182
|
+
repo_id: 'my-model'
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# List files in a repository
|
|
186
|
+
files = api.list_repo_files(
|
|
187
|
+
repo_id: 'gpt2',
|
|
188
|
+
revision: 'main'
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Searching and Listing
|
|
193
|
+
|
|
194
|
+
Find models, datasets, and spaces:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
api = HuggingfaceHub::HfApi.new
|
|
198
|
+
|
|
199
|
+
# List all text generation models
|
|
200
|
+
models = api.list_models(
|
|
201
|
+
filter: 'text-generation',
|
|
202
|
+
sort: 'downloads',
|
|
203
|
+
limit: 10
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
models.each do |model|
|
|
207
|
+
puts "#{model.id} - #{model.downloads} downloads"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# List datasets
|
|
211
|
+
datasets = api.list_datasets(
|
|
212
|
+
filter: 'translation',
|
|
213
|
+
language: 'en'
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# List spaces
|
|
217
|
+
spaces = api.list_spaces(
|
|
218
|
+
filter: 'gradio',
|
|
219
|
+
limit: 5
|
|
220
|
+
)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Working with Model Cards
|
|
224
|
+
|
|
225
|
+
Read and write repository cards:
|
|
226
|
+
|
|
227
|
+
```ruby
|
|
228
|
+
# Load a model card
|
|
229
|
+
card = HuggingfaceHub::ModelCard.load(repo_id: 'gpt2')
|
|
230
|
+
puts card.data.tags
|
|
231
|
+
puts card.text
|
|
232
|
+
|
|
233
|
+
# Create a new model card
|
|
234
|
+
card = HuggingfaceHub::ModelCard.new(
|
|
235
|
+
text: "# My Model\n\nThis is my awesome model.",
|
|
236
|
+
data: {
|
|
237
|
+
language: 'en',
|
|
238
|
+
license: 'apache-2.0',
|
|
239
|
+
tags: ['text-generation']
|
|
240
|
+
}
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Save to repository
|
|
244
|
+
card.push_to_hub(repo_id: 'my-model')
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Caching and Offline Mode
|
|
248
|
+
|
|
249
|
+
Control caching behavior:
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
# Specify custom cache directory
|
|
253
|
+
HuggingfaceHub.config.cache_dir = '/path/to/cache'
|
|
254
|
+
|
|
255
|
+
# Enable offline mode (only use cached files)
|
|
256
|
+
HuggingfaceHub.config.offline = true
|
|
257
|
+
|
|
258
|
+
# Scan cache to see what's stored
|
|
259
|
+
cache_info = HuggingfaceHub.scan_cache_dir
|
|
260
|
+
|
|
261
|
+
cache_info.repos.each do |repo|
|
|
262
|
+
puts "#{repo.repo_id}: #{repo.size_on_disk_str}"
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Clean up cache
|
|
266
|
+
strategy = cache_info.delete_revisions(*old_revisions)
|
|
267
|
+
strategy.execute
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Error Handling
|
|
271
|
+
|
|
272
|
+
The library provides detailed error messages:
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
begin
|
|
276
|
+
HuggingfaceHub.hf_hub_download(
|
|
277
|
+
repo_id: 'nonexistent/model',
|
|
278
|
+
filename: 'config.json'
|
|
279
|
+
)
|
|
280
|
+
rescue HuggingfaceHub::RepositoryNotFoundError => e
|
|
281
|
+
puts "Repository not found: #{e.message}"
|
|
282
|
+
rescue HuggingfaceHub::RevisionNotFoundError => e
|
|
283
|
+
puts "Revision not found: #{e.message}"
|
|
284
|
+
rescue HuggingfaceHub::EntryNotFoundError => e
|
|
285
|
+
puts "File not found: #{e.message}"
|
|
286
|
+
rescue HuggingfaceHub::HfHubHTTPError => e
|
|
287
|
+
puts "HTTP error: #{e.message}"
|
|
288
|
+
puts "Status code: #{e.response.status}"
|
|
289
|
+
end
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Configuration
|
|
293
|
+
|
|
294
|
+
Configure library behavior via environment variables:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
# Authentication
|
|
298
|
+
export HF_TOKEN='hf_...'
|
|
299
|
+
|
|
300
|
+
# Cache location
|
|
301
|
+
export HF_HOME=~/.cache/huggingface
|
|
302
|
+
export HF_HUB_CACHE=~/.cache/huggingface/hub
|
|
303
|
+
|
|
304
|
+
# Hub endpoint (for custom/enterprise instances)
|
|
305
|
+
export HF_ENDPOINT=https://huggingface.co
|
|
306
|
+
|
|
307
|
+
# Behavior
|
|
308
|
+
export HF_HUB_OFFLINE=1 # Enable offline mode
|
|
309
|
+
export HF_HUB_DISABLE_PROGRESS_BARS=1 # Hide progress bars
|
|
310
|
+
export HF_HUB_DISABLE_TELEMETRY=1 # Opt out of telemetry
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Or configure programmatically:
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
HuggingfaceHub.configure do |config|
|
|
317
|
+
config.cache_dir = '/custom/cache/path'
|
|
318
|
+
config.endpoint = 'https://huggingface.co'
|
|
319
|
+
config.offline = false
|
|
320
|
+
config.progress_bars = true
|
|
321
|
+
config.token = ENV['HF_TOKEN']
|
|
322
|
+
end
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## API Reference
|
|
326
|
+
|
|
327
|
+
See the [API Documentation](https://rubydoc.info/gems/huggingface_hub) for complete reference.
|
|
328
|
+
|
|
329
|
+
### Core Classes
|
|
330
|
+
|
|
331
|
+
- **HfApi**: Main API client for all Hub operations
|
|
332
|
+
- **ModelCard**, **DatasetCard**, **SpaceCard**: Repository card management
|
|
333
|
+
- **CacheManager**: Cache inspection and cleanup
|
|
334
|
+
|
|
335
|
+
### Core Functions
|
|
336
|
+
|
|
337
|
+
- `hf_hub_download`: Download a single file from a repository
|
|
338
|
+
- `snapshot_download`: Download an entire repository
|
|
339
|
+
- `login`/`logout`: Authentication management
|
|
340
|
+
- `scan_cache_dir`: Inspect cached files
|
|
341
|
+
|
|
342
|
+
## Architecture
|
|
343
|
+
|
|
344
|
+
The library is organized into modular components:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
lib/durable_huggingface_hub/
|
|
348
|
+
├── hf_api.rb # Main API client
|
|
349
|
+
├── file_download.rb # Download utilities
|
|
350
|
+
├── constants.rb # Configuration constants
|
|
351
|
+
├── errors.rb # Error hierarchy
|
|
352
|
+
├── authentication.rb # Token management
|
|
353
|
+
├── cache.rb # Caching system
|
|
354
|
+
├── repository_card.rb # Model/dataset cards
|
|
355
|
+
└── utils/ # Utility modules
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Design Philosophy
|
|
359
|
+
|
|
360
|
+
This library follows Durable Programming's core principles:
|
|
361
|
+
|
|
362
|
+
- **Pragmatic Problem-Solving**: Solve real-world ML deployment needs with practical solutions
|
|
363
|
+
- **Sustainability**: Design for long-term maintenance and evolution
|
|
364
|
+
- **Quality**: Comprehensive testing, validation, and error handling
|
|
365
|
+
- **Transparency**: Clear documentation and honest capability representation
|
|
366
|
+
- **Incremental Improvement**: Build on proven patterns from the Python implementation
|
|
367
|
+
|
|
368
|
+
## Feature Comparison with Python Client
|
|
369
|
+
|
|
370
|
+
This Ruby implementation aims to provide feature parity with the official Python `huggingface_hub` library while following Ruby conventions. The table below tracks implementation progress:
|
|
371
|
+
|
|
372
|
+
### Core Features
|
|
373
|
+
|
|
374
|
+
| Feature | Python | Ruby | Status |
|
|
375
|
+
|---------|--------|------|--------|
|
|
376
|
+
| **File Operations** |
|
|
377
|
+
| Download single file (`hf_hub_download`) | ✓ | ✓ | Complete |
|
|
378
|
+
| Download repository snapshot | ✓ | ✓ | Complete |
|
|
379
|
+
| Upload single file | ✓ | ✓ | Complete |
|
|
380
|
+
| Upload folder | ✓ | ✓ | Complete |
|
|
381
|
+
| Delete files | ✓ | ✓ | Complete |
|
|
382
|
+
| **Authentication** |
|
|
383
|
+
| Token management | ✓ | ✓ | Complete |
|
|
384
|
+
| Login/logout | ✓ | ✓ | Complete |
|
|
385
|
+
| User info (`whoami`) | ✓ | ✓ | Complete |
|
|
386
|
+
| Git credential integration | ✓ | ✓ | Complete |
|
|
387
|
+
| **Repository Management** |
|
|
388
|
+
| Create repository | ✓ | ✓ | Complete |
|
|
389
|
+
| Delete repository | ✓ | ✓ | Complete |
|
|
390
|
+
| Update repository visibility | ✓ | ✓ | Complete |
|
|
391
|
+
| Repository info | ✓ | ✓ | Complete |
|
|
392
|
+
| Check repository exists | ✓ | ✓ | Complete |
|
|
393
|
+
| List repository files | ✓ | ✓ | Complete |
|
|
394
|
+
| **Search & Discovery** |
|
|
395
|
+
| List models | ✓ | ✓ | Complete |
|
|
396
|
+
| List datasets | ✓ | ✓ | Complete |
|
|
397
|
+
| List spaces | ✓ | ✓ | Complete |
|
|
398
|
+
| Filter by tags/author | ✓ | ✓ | Complete |
|
|
399
|
+
| **Cache Management** |
|
|
400
|
+
| Scan cache directory | ✓ | ✓ | Complete |
|
|
401
|
+
| Delete cached revisions | ✓ | ✓ | Complete |
|
|
402
|
+
| Cache info dataclasses | ✓ | ✓ | Complete |
|
|
403
|
+
| **Repository Cards** |
|
|
404
|
+
| Load model cards | ✓ | ✓ | Complete |
|
|
405
|
+
| Create model cards | ✓ | ✓ | Complete |
|
|
406
|
+
| Update model cards | ✓ | ✓ | Complete |
|
|
407
|
+
| Dataset cards | ✓ | ✓ | Complete |
|
|
408
|
+
| Space cards | ✓ | ✓ | Complete |
|
|
409
|
+
|
|
410
|
+
### Advanced Features
|
|
411
|
+
|
|
412
|
+
| Feature | Python | Ruby | Status |
|
|
413
|
+
|---------|--------|------|--------|
|
|
414
|
+
| **Inference** |
|
|
415
|
+
| Inference client | ✓ | ✗ | Not planned v1.0 |
|
|
416
|
+
| Inference endpoints | ✓ | ✗ | Not planned v1.0 |
|
|
417
|
+
| **Community Features** |
|
|
418
|
+
| Discussions | ✓ | ✗ | Not planned v1.0 |
|
|
419
|
+
| Pull requests | ✓ | ✗ | Not planned v1.0 |
|
|
420
|
+
| Comments | ✓ | ✗ | Not planned v1.0 |
|
|
421
|
+
| **Spaces** |
|
|
422
|
+
| Runtime management | ✓ | ✗ | Not planned v1.0 |
|
|
423
|
+
| Secrets management | ✓ | ✗ | Not planned v1.0 |
|
|
424
|
+
| Hardware requests | ✓ | ✗ | Not planned v1.0 |
|
|
425
|
+
| **Other** |
|
|
426
|
+
| Webhooks server | ✓ | ✗ | Not planned v1.0 |
|
|
427
|
+
| Collections | ✓ | ✗ | Not planned v1.0 |
|
|
428
|
+
| OAuth | ✓ | ✗ | Not planned v1.0 |
|
|
429
|
+
| HfFileSystem (fsspec) | ✓ | ✗ | Not planned v1.0 |
|
|
430
|
+
| TensorBoard integration | ✓ | ✗ | Not planned v1.0 |
|
|
431
|
+
|
|
432
|
+
**Legend:**
|
|
433
|
+
- ✓ Implemented
|
|
434
|
+
- ⚠️ Planned for v1.0
|
|
435
|
+
- ✗ Not planned for v1.0
|
|
436
|
+
|
|
437
|
+
The Ruby implementation focuses on core functionality that Ruby developers need for downloading models and datasets, managing repositories, and basic Hub interactions. Advanced features like inference clients and community features may be added in future versions based on community feedback.
|
|
438
|
+
|
|
439
|
+
## Ruby-Specific Design Choices
|
|
440
|
+
|
|
441
|
+
While maintaining API compatibility where practical, this Ruby implementation:
|
|
442
|
+
|
|
443
|
+
- Uses Ruby idioms and conventions (snake_case, blocks, keyword arguments)
|
|
444
|
+
- Leverages Ruby's standard library for HTTP and file operations
|
|
445
|
+
- Employs Ruby-native gems for validation and type checking
|
|
446
|
+
- Provides Ruby-friendly error handling with proper exception hierarchy
|
|
447
|
+
- Uses Ruby's module system for code organization
|
|
448
|
+
- Follows Ruby community standards for gem structure and distribution
|
|
449
|
+
|
|
450
|
+
## Contributing
|
|
451
|
+
|
|
452
|
+
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|
453
|
+
|
|
454
|
+
- Development setup instructions
|
|
455
|
+
- Code style guidelines
|
|
456
|
+
- Testing requirements
|
|
457
|
+
- Pull request process
|
|
458
|
+
|
|
459
|
+
## Development
|
|
460
|
+
|
|
461
|
+
Clone the repository:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
git clone https://github.com/durableprogramming/huggingface-hub-ruby.git
|
|
465
|
+
cd huggingface-hub-ruby
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Install dependencies:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
bundle install
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Run tests:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
bundle exec rake test
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Run linter:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
bundle exec rubocop
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## Testing
|
|
487
|
+
|
|
488
|
+
The library includes comprehensive tests:
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
# Run all tests
|
|
492
|
+
bundle exec rake test
|
|
493
|
+
|
|
494
|
+
# Run specific test file
|
|
495
|
+
bundle exec ruby test/huggingface_hub/hf_api_test.rb
|
|
496
|
+
|
|
497
|
+
# Run with coverage
|
|
498
|
+
bundle exec rake test:coverage
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## License
|
|
502
|
+
|
|
503
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
504
|
+
|
|
505
|
+
## Acknowledgments
|
|
506
|
+
|
|
507
|
+
This is a pure Ruby port of the [HuggingFace Hub Python library](https://github.com/huggingface/huggingface_hub). We are grateful to the HuggingFace team for creating the original library and for their contributions to open-source AI tooling.
|
|
508
|
+
|
|
509
|
+
## Support
|
|
510
|
+
|
|
511
|
+
- Documentation: [https://rubydoc.info/gems/huggingface_hub](https://rubydoc.info/gems/huggingface_hub)
|
|
512
|
+
- Issues: [GitHub Issues](https://github.com/durableprogramming/huggingface-hub-ruby/issues)
|
|
513
|
+
- Email: commercial@durableprogramming.com
|
|
514
|
+
|
|
515
|
+
## Roadmap
|
|
516
|
+
|
|
517
|
+
### v0.2.0 (Current) - Feature Complete ✓
|
|
518
|
+
- ✓ Constants and configuration
|
|
519
|
+
- ✓ Error hierarchy
|
|
520
|
+
- ✓ Authentication (login, logout, whoami)
|
|
521
|
+
- ✓ File download with caching
|
|
522
|
+
- ✓ File upload operations (single file and folders)
|
|
523
|
+
- ✓ Repository creation, deletion, and management
|
|
524
|
+
- ✓ Repository information (models, datasets, spaces)
|
|
525
|
+
- ✓ Search and listing (models, datasets, spaces)
|
|
526
|
+
- ✓ Repository cards (model, dataset, space)
|
|
527
|
+
- ✓ Complete cache management with deletion support
|
|
528
|
+
- ✓ LFS detection and handling
|
|
529
|
+
|
|
530
|
+
### Planned for v1.0.0
|
|
531
|
+
- [ ] Additional repository management features (move, duplicate, update settings)
|
|
532
|
+
- [ ] Comprehensive integration testing with live Hub
|
|
533
|
+
- [ ] Production-ready error handling and retry logic
|
|
534
|
+
- [ ] Performance optimizations
|
|
535
|
+
- [ ] Complete documentation and usage examples
|
|
536
|
+
|
|
537
|
+
### Future Considerations
|
|
538
|
+
Advanced features from the Python client may be added based on community needs:
|
|
539
|
+
- Inference client and endpoints
|
|
540
|
+
- Community features (discussions, PRs)
|
|
541
|
+
- Spaces runtime management
|
|
542
|
+
- Webhooks and collections
|
|
543
|
+
- OAuth integration
|
|
544
|
+
|
|
545
|
+
## Changelog
|
|
546
|
+
|
|
547
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
require "rubocop/rake_task"
|
|
6
|
+
|
|
7
|
+
# Test tasks
|
|
8
|
+
Rake::TestTask.new(:test) do |t|
|
|
9
|
+
t.libs << "test"
|
|
10
|
+
t.libs << "lib"
|
|
11
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
12
|
+
t.verbose = true
|
|
13
|
+
t.warning = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
namespace :test do
|
|
17
|
+
desc "Run tests with coverage"
|
|
18
|
+
task :coverage do
|
|
19
|
+
ENV["COVERAGE"] = "true"
|
|
20
|
+
Rake::Task[:test].execute
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
desc "Run integration tests"
|
|
24
|
+
Rake::TestTask.new(:integration) do |t|
|
|
25
|
+
t.libs << "test"
|
|
26
|
+
t.libs << "lib"
|
|
27
|
+
t.test_files = FileList["test/integration/**/*_test.rb"]
|
|
28
|
+
t.verbose = true
|
|
29
|
+
t.warning = false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# RuboCop tasks
|
|
34
|
+
RuboCop::RakeTask.new do |task|
|
|
35
|
+
task.options = ["--display-cop-names"]
|
|
36
|
+
task.fail_on_error = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
namespace :rubocop do
|
|
40
|
+
desc "Auto-correct RuboCop offenses"
|
|
41
|
+
RuboCop::RakeTask.new(:autocorrect) do |task|
|
|
42
|
+
task.options = ["--auto-correct", "--display-cop-names"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
desc "Auto-correct RuboCop offenses (including unsafe)"
|
|
46
|
+
RuboCop::RakeTask.new(:autocorrect_all) do |task|
|
|
47
|
+
task.options = ["--auto-correct-all", "--display-cop-names"]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# YARD documentation tasks
|
|
52
|
+
begin
|
|
53
|
+
require "yard"
|
|
54
|
+
|
|
55
|
+
YARD::Rake::YardocTask.new(:yard) do |t|
|
|
56
|
+
t.files = ["lib/**/*.rb"]
|
|
57
|
+
t.options = ["--output-dir", "doc", "--readme", "README.md"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
namespace :yard do
|
|
61
|
+
desc "Generate YARD documentation and open in browser"
|
|
62
|
+
task :server do
|
|
63
|
+
sh "yard server --reload"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
desc "List undocumented objects"
|
|
67
|
+
task :stats do
|
|
68
|
+
sh "yard stats --list-undoc"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
rescue LoadError
|
|
72
|
+
# YARD not available
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Default task
|
|
76
|
+
task default: %i[rubocop test]
|
|
77
|
+
|
|
78
|
+
# Build task
|
|
79
|
+
desc "Build the gem"
|
|
80
|
+
task :build do
|
|
81
|
+
sh "gem build huggingface_hub.gemspec"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Install task
|
|
85
|
+
desc "Build and install the gem locally"
|
|
86
|
+
task install: :build do
|
|
87
|
+
sh "gem install huggingface_hub-*.gem"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Clean task
|
|
91
|
+
desc "Clean up generated files"
|
|
92
|
+
task :clean do
|
|
93
|
+
sh "rm -f huggingface_hub-*.gem"
|
|
94
|
+
sh "rm -rf doc/"
|
|
95
|
+
sh "rm -rf coverage/"
|
|
96
|
+
sh "rm -rf tmp/"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Console task for interactive testing
|
|
100
|
+
desc "Open an IRB console with the gem loaded"
|
|
101
|
+
task :console do
|
|
102
|
+
require "irb"
|
|
103
|
+
require "huggingface_hub"
|
|
104
|
+
ARGV.clear
|
|
105
|
+
IRB.start
|
|
106
|
+
end
|