Skip to content

Commit 0bc9d0c

Browse files
Fix ergonomics issues (#339)
Provides some ergonomics fixes in the Python bindings. Closes #336 Closes #337 Closes #338
1 parent c03ed80 commit 0bc9d0c

5 files changed

Lines changed: 30 additions & 54 deletions

File tree

encoderfile-py/python/encoderfile/_core.pyi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class EncoderfileBuilder:
1414
def from_config(
1515
config: str,
1616
) -> "EncoderfileBuilder": ...
17-
@staticmethod
18-
def from_dict(
17+
def __new__(
18+
cls,
1919
*,
2020
name: str,
2121
version: Optional[str] = None,
@@ -45,8 +45,8 @@ class TokenizerBuildConfig:
4545
max_length: Optional[int]
4646
stride: Optional[int]
4747

48-
@staticmethod
49-
def new(
48+
def __new__(
49+
cls,
5050
*,
5151
pad_strategy: Optional[str] = None,
5252
truncation_side: Optional[str] = None,

encoderfile-py/python/tests/assets/test_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ encoderfile:
33
path: models/token_classification
44
model_type: token_classification
55
output_path: /tmp/test-model.encoderfile
6+
base_binary_path: ./target/debug/encoderfile-runtime
67
transform: |
78
--- Applies a softmax across token classification logits.
89
--- Each token classification is normalized independently.

encoderfile-py/python/tests/assets/test_config_lua.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ encoderfile:
33
path: models/token_classification
44
model_type: token_classification
55
output_path: /tmp/test-model-lua.encoderfile
6+
base_binary_path: ./target/debug/encoderfile-runtime
67
lua_libs:
78
- table
89
- math

encoderfile-py/python/tests/test_encoderfile.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test_encoderfilebuilder_from_config_fails():
4343
""",
4444
}
4545
with pytest.raises(RuntimeError) as exc_info:
46-
EncoderfileBuilder.from_dict(**config)
46+
EncoderfileBuilder(**config)
4747
assert "Invalid model type" in str(exc_info.value)
4848

4949

@@ -70,7 +70,7 @@ def test_encoderfilebuilder_from_config_returns_builder():
7070
end
7171
""",
7272
}
73-
builder = EncoderfileBuilder.from_dict(**config)
73+
builder = EncoderfileBuilder(**config)
7474
assert isinstance(builder, EncoderfileBuilder)
7575

7676

@@ -104,9 +104,10 @@ def test_encoderfilebuilder_build_from_dict(tmp_path):
104104
"path": "models/token_classification",
105105
"model_type": ModelType.TokenClassification,
106106
"output_path": str(tmp_path / f"{name}.encoderfile"),
107-
"tokenizer": TokenizerBuildConfig.new(
107+
"tokenizer": TokenizerBuildConfig(
108108
pad_strategy="batch_longest",
109109
),
110+
"base_binary_path": "./target/debug/encoderfile-runtime",
110111
"transform": """
111112
--- No docs
112113
---
@@ -125,7 +126,7 @@ def test_encoderfilebuilder_build_from_dict(tmp_path):
125126
}
126127
model_info = load_json(Path(config["path"]) / "config.json")
127128
print(model_info)
128-
builder = EncoderfileBuilder.from_dict(**config)
129+
builder = EncoderfileBuilder(**config)
129130
# Should not raise
130131
builder.build(workdir=None, version=None, no_download=True)
131132
result = inspect(config["output_path"])
@@ -172,7 +173,7 @@ def test_encoderfilebuilder_build_all_from_dict(tmp_path):
172173
end
173174
""",
174175
"lua_libs": ["table", "math"],
175-
"tokenizer": TokenizerBuildConfig.new(
176+
"tokenizer": TokenizerBuildConfig(
176177
pad_strategy="batch_longest",
177178
truncation_side="right",
178179
truncation_strategy="longest_first",
@@ -182,7 +183,7 @@ def test_encoderfilebuilder_build_all_from_dict(tmp_path):
182183
"validate_transform": False,
183184
"target": "x86_64-unknown-linux-musl",
184185
}
185-
builder = EncoderfileBuilder.from_dict(**config)
186+
builder = EncoderfileBuilder(**config)
186187
builder.build(workdir=None, version=None, no_download=True)
187188
result = inspect(config["output_path"])
188189
assert isinstance(result, InspectInfo)
@@ -205,7 +206,7 @@ def test_encoderfilebuilder_with_target_spec_object(tmp_path):
205206
"path": "models/token_classification",
206207
"model_type": ModelType.TokenClassification,
207208
"output_path": str(tmp_path / f"{name}.encoderfile"),
208-
"tokenizer": TokenizerBuildConfig.new(
209+
"tokenizer": TokenizerBuildConfig(
209210
pad_strategy="batch_longest",
210211
),
211212
"transform": """
@@ -225,7 +226,7 @@ def test_encoderfilebuilder_with_target_spec_object(tmp_path):
225226
""",
226227
"target": target_spec,
227228
}
228-
EncoderfileBuilder.from_dict(**config)
229+
EncoderfileBuilder(**config)
229230

230231

231232
def test_encoderfilebuilder_wrong_arch(tmp_path):
@@ -235,7 +236,7 @@ def test_encoderfilebuilder_wrong_arch(tmp_path):
235236
"path": "models/token_classification",
236237
"model_type": ModelType.TokenClassification,
237238
"output_path": str(tmp_path / f"{name}.encoderfile"),
238-
"tokenizer": TokenizerBuildConfig.new(
239+
"tokenizer": TokenizerBuildConfig(
239240
pad_strategy="batch_longest",
240241
),
241242
"transform": """
@@ -256,7 +257,7 @@ def test_encoderfilebuilder_wrong_arch(tmp_path):
256257
"target": "nonsense!",
257258
}
258259
with pytest.raises(ValueError) as exc_info:
259-
EncoderfileBuilder.from_dict(**config)
260+
EncoderfileBuilder(**config)
260261
assert (
261262
f"Failed to parse target spec: invalid or unsupported target triple `{config['target']}`"
262263
in str(exc_info.value)
@@ -271,7 +272,7 @@ def test_tokenizer_build_config_from_dict():
271272
"max_length": 512,
272273
"stride": 0,
273274
}
274-
tokenizer_config = TokenizerBuildConfig.new(**config)
275+
tokenizer_config = TokenizerBuildConfig(**config)
275276
assert tokenizer_config.pad_strategy == config["pad_strategy"]
276277
assert tokenizer_config.truncation_side == config["truncation_side"]
277278
assert tokenizer_config.truncation_strategy == config["truncation_strategy"]
@@ -288,7 +289,7 @@ def test_tokenizer_wrong_config_pad_strategy():
288289
"stride": 0,
289290
}
290291
with pytest.raises(RuntimeError) as exc_info:
291-
TokenizerBuildConfig.new(**config)
292+
TokenizerBuildConfig(**config)
292293
assert f"Invalid pad strategy: {config['pad_strategy']}" in str(exc_info.value)
293294

294295

@@ -301,7 +302,7 @@ def test_tokenizer_wrong_config_truncation_side():
301302
"stride": 0,
302303
}
303304
with pytest.raises(RuntimeError) as exc_info:
304-
TokenizerBuildConfig.new(**config)
305+
TokenizerBuildConfig(**config)
305306
assert f"Invalid truncation side: {config['truncation_side']}" in str(
306307
exc_info.value
307308
)
@@ -316,7 +317,7 @@ def test_tokenizer_wrong_config_truncation_strategy():
316317
"stride": 0,
317318
}
318319
with pytest.raises(RuntimeError) as exc_info:
319-
TokenizerBuildConfig.new(**config)
320+
TokenizerBuildConfig(**config)
320321
assert f"Invalid truncation strategy: {config['truncation_strategy']}" in str(
321322
exc_info.value
322323
)
@@ -331,7 +332,7 @@ def test_tokenizer_wrong_config_max_length():
331332
"stride": 0,
332333
}
333334
with pytest.raises(OverflowError):
334-
TokenizerBuildConfig.new(**config)
335+
TokenizerBuildConfig(**config)
335336

336337

337338
def test_tokenizer_wrong_type_max_length():
@@ -343,7 +344,7 @@ def test_tokenizer_wrong_type_max_length():
343344
"stride": 0,
344345
}
345346
with pytest.raises(TypeError) as exc_info:
346-
TokenizerBuildConfig.new(**config)
347+
TokenizerBuildConfig(**config)
347348
assert "'str' object cannot be interpreted as an integer" in str(exc_info.value)
348349

349350

@@ -356,7 +357,7 @@ def test_tokenizer_wrong_config_stride():
356357
"stride": -1,
357358
}
358359
with pytest.raises(OverflowError):
359-
TokenizerBuildConfig.new(**config)
360+
TokenizerBuildConfig(**config)
360361

361362

362363
def test_tokenizer_wrong_type_stride():
@@ -368,7 +369,7 @@ def test_tokenizer_wrong_type_stride():
368369
"stride": "nonsense!",
369370
}
370371
with pytest.raises(TypeError) as exc_info:
371-
TokenizerBuildConfig.new(**config)
372+
TokenizerBuildConfig(**config)
372373
assert "'str' object cannot be interpreted as an integer" in str(exc_info.value)
373374

374375

@@ -380,7 +381,7 @@ def test_tokenizer_config_optional_fields():
380381
"max_length": None,
381382
"stride": None,
382383
}
383-
tokenizer_config = TokenizerBuildConfig.new(**config)
384+
tokenizer_config = TokenizerBuildConfig(**config)
384385
assert tokenizer_config.pad_strategy is None
385386
assert tokenizer_config.truncation_side is None
386387
assert tokenizer_config.truncation_strategy is None
@@ -390,7 +391,7 @@ def test_tokenizer_config_optional_fields():
390391

391392
def test_tokenizer_config_all_optional_fields():
392393
config = {}
393-
tokenizer_config = TokenizerBuildConfig.new(**config)
394+
tokenizer_config = TokenizerBuildConfig(**config)
394395
assert tokenizer_config.pad_strategy is None
395396
assert tokenizer_config.truncation_side is None
396397
assert tokenizer_config.truncation_strategy is None
@@ -403,7 +404,7 @@ def test_tokenizer_config_partial_optional_fields():
403404
"pad_strategy": "batch_longest",
404405
"max_length": 512,
405406
}
406-
tokenizer_config = TokenizerBuildConfig.new(**config)
407+
tokenizer_config = TokenizerBuildConfig(**config)
407408
assert tokenizer_config.pad_strategy == config["pad_strategy"]
408409
assert tokenizer_config.truncation_side is None
409410
assert tokenizer_config.truncation_strategy is None

encoderfile-py/src/builder.rs

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,13 @@ use pyo3::{
1919
prelude::*,
2020
};
2121

22-
#[pyclass(name = "Transform", frozen)]
23-
pub struct PyTransform(Transform);
24-
25-
#[pymethods]
26-
impl PyTransform {
27-
#[staticmethod]
28-
fn path(path: String) -> Self {
29-
PyTransform(Transform::Path { path: path.into() })
30-
}
31-
#[staticmethod]
32-
fn inline(inline: String) -> Self {
33-
PyTransform(Transform::Inline(inline))
34-
}
35-
fn is_inline(&self) -> bool {
36-
matches!(self.0, Transform::Inline(_))
37-
}
38-
fn is_path(&self) -> bool {
39-
matches!(self.0, Transform::Path { .. })
40-
}
41-
fn __str__(&self) -> String {
42-
match &self.0 {
43-
Transform::Path { path } => format!("Path({})", path.display()),
44-
Transform::Inline(inline) => format!("Inline({})", inline),
45-
}
46-
}
47-
}
48-
4922
#[pyclass(name = "TokenizerBuildConfig", frozen)]
5023
pub struct PyTokenizerBuildConfig(TokenizerBuildConfig);
5124

5225
#[pymethods]
5326
impl PyTokenizerBuildConfig {
5427
#[allow(clippy::too_many_arguments)]
55-
#[staticmethod]
28+
#[new]
5629
#[pyo3(signature = (*, pad_strategy = None, truncation_side = None, truncation_strategy = None, max_length = None, stride = None))]
5730
pub fn new(
5831
pad_strategy: Option<String>,
@@ -129,7 +102,7 @@ impl PyEncoderfileBuilder {
129102
}
130103

131104
#[allow(clippy::too_many_arguments)]
132-
#[staticmethod]
105+
#[new]
133106
#[pyo3(signature = (*, name, version = None, model_type, path, output_path = None, cache_dir = None, base_binary_path = None, transform = None, lua_libs = None, tokenizer = None, validate_transform = true, target = None))]
134107
fn from_dict(
135108
name: String,

0 commit comments

Comments
 (0)