Skip to content

Restore deprecated regex DSL functions with a warning #1532

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 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions outlines/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
between,
one_or_more,
zero_or_more,
# deprecated
repeat,
times,
)

# Python types
Expand Down
101 changes: 101 additions & 0 deletions outlines/types/dsl.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json as json
import re
import warnings
from dataclasses import dataclass
from typing import Any, List, Union

Expand Down Expand Up @@ -124,6 +125,15 @@ def one_or_more(self) -> "KleenePlus":
def zero_or_more(self) -> "KleeneStar":
return zero_or_more(self)

# deprecated
def times(self, count: int) -> "QuantifyExact":
return times(self, count)

def repeat(self, min_count: int, max_count: int) -> Union[
"QuantifyMinimum", "QuantifyMaximum", "QuantifyBetween"
]:
return repeat(self, min_count, max_count)


@dataclass
class String(Term):
Expand Down Expand Up @@ -374,6 +384,97 @@ def one_or_more(term: Union[Term, str]) -> KleenePlus:
return KleenePlus(term)


def repeat(term: Term, min_count: int, max_count: int) -> Union[
QuantifyMinimum, QuantifyMaximum, QuantifyBetween
]:
if min_count is None and max_count is None:
warnings.warn("""
The `repeat` function/method is deprecated starting from v0.2.2.
Do not use it. Support for it will be removed in v1.5.0.
Use `between`, `at_least` or `at_most` instead.
""",
DeprecationWarning,
stacklevel=2,
)
raise ValueError(
"You must provide a value for at least `min_count` or `max_count`"
)
if max_count is None:
warnings.warn("""
The `repeat` function/method is deprecated starting from v0.2.2.
Do not use it. Support for it will be removed in v1.5.0.
Use `at_least` instead.
For instance:
```python
from outlines.types import Regex, at_least
digit = Regex(r'[0-9]')
# 2 ways of doing the same thing
at_least_5_digits = digit.at_least(5)
at_least_5_digits = at_least(digit, 5)
```
""",
DeprecationWarning,
stacklevel=2,
)
return at_least(min_count, term)
if min_count is None:
warnings.warn("""
The `repeat` function/method is deprecated starting from v0.2.2.
Do not use it. Support for it will be removed in v1.5.0.
Use `at_most` instead.
For instance:
```python
from outlines.types import Regex, at_most
digit = Regex(r'[0-9]')
# 2 ways of doing the same thing
at_most_5_digits = digit.at_most(5)
at_most_5_digits = at_most(digit, 5)
```
""",
DeprecationWarning,
stacklevel=2,
)
return at_most(max_count, term)
else:
warnings.warn("""
The `repeat` function/method is deprecated starting from v0.2.2.
Do not use it. Support for it will be removed in v1.5.0.
Use `between` instead.
For instance:
```python
from outlines.types import Regex, between
digit = Regex(r'[0-9]')
# 2 ways of doing the same thing
five_to_eight_digits = digit.between(5, 8)
five_to_eight_digits = between(digit, 5, 8)
```
""",
DeprecationWarning,
stacklevel=2,
)
return between(min_count, max_count, term)


def times(term: Term, count: int) -> QuantifyExact:
warnings.warn("""
The `times` function/method is deprecated starting from v0.2.2.
Do not use it. Support for it will be removed in v1.5.0.
Use `exactly` instead.
For instance:
```python
from outlines.types import Regex, exactly
digit = Regex(r'[0-9]')
# 2 ways of doing the same thing
five_digits = digit.exactly(5)
five_digits = exactly(digit, 5)
```
""",
DeprecationWarning,
stacklevel=2,
)
return exactly(count, term)


def to_regex(term: Term) -> str:
"""Convert a term to a regular expression.

Expand Down
2 changes: 1 addition & 1 deletion tests/generate/test_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def model_t5(tmp_path_factory):
"model_transformers_random",
"model_transformers_opt125m",
"model_mamba",
"model_bart",
#"model_bart",
"model_transformers_vision",
"model_vllm",
)
Expand Down
46 changes: 46 additions & 0 deletions tests/types/test_dsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
exactly,
regex,
json_schema,
# deprecated
repeat,
times,
)


Expand Down Expand Up @@ -252,6 +255,49 @@ def test_dsl_aliases():
assert isinstance(test, JsonSchema)


def test_dsl_repeat():
with pytest.warns(
DeprecationWarning,
match="The `repeat` function/method is deprecated",
):
a = String("a")

# error missing min_count or max_count
with pytest.raises(
ValueError,
match="You must provide a value for at least `min_count` or "
"`max_count`",
):
repeat(a, None, None)

# at_least
assert repeat(a, 2, None) == at_least(2, a)
assert repeat("a", 2, None) == at_least(2, "a")
assert a.repeat(2, None) == a.at_least(2)

# at_most
assert repeat(a, None, 2) == at_most(2, a)
assert repeat("a", None, 2) == at_most(2, "a")
assert a.repeat(None, 2) == a.at_most(2)

# between
assert repeat(a, 1, 2) == between(1, 2, a)
assert repeat("a", 1, 2) == between(1, 2, "a")
assert a.repeat(1, 2) == a.between(1, 2)


def test_dsl_times():
with pytest.warns(
DeprecationWarning,
match="The `times` function/method is deprecated",
):
a = String("a")

assert times(a, 2) == exactly(2, a)
assert times("a", 2) == exactly(2, "a")
assert a.times(2) == a.exactly(2)


def test_dsl_term_pydantic_simple():
a = String("a")

Expand Down
Loading