Skip to content

Commit ed506e2

Browse files
committed
Update library
1 parent 76b6cce commit ed506e2

7 files changed

Lines changed: 311 additions & 228 deletions

File tree

‎regexsolver/clients/asynchronous.py‎

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import asyncio
22
import logging
33
import weakref
4-
from typing import List, Optional, Union
4+
from typing import List, Optional
55

66
from regexsolver.clients.rate_limiter import get_rate_limiter
77
from regexsolver.exceptions import (
@@ -38,7 +38,7 @@
3838
TermRequest,
3939
TwoTermsRequest,
4040
)
41-
from regexsolver.models.cardinality import BigInteger, Infinite, Integer
41+
from regexsolver.models.cardinality import Cardinality, Infinite, Integer
4242
from regexsolver.models.length import Length
4343
from regexsolver.models.response_format import ResponseFormat
4444
from regexsolver.models.term import Term
@@ -202,7 +202,7 @@ def _map_error(self, e: ApiException) -> Exception:
202202
def _build_options(
203203
self,
204204
execution_timeout: Optional[int] = None,
205-
response_format: Optional[Union[ResponseFormat, str]] = None,
205+
response_format: Optional[ResponseFormat] = None,
206206
) -> RequestOptions:
207207
options = RequestOptions(schemaVersion=1)
208208
if execution_timeout is not None:
@@ -214,7 +214,7 @@ def _build_options(
214214
# --- ANALYZE ---
215215
async def get_cardinality(
216216
self, term: Term, execution_timeout: Optional[int] = None
217-
):
217+
) -> Cardinality:
218218
"""Computes how many unique strings the term matches.
219219
220220
Args:
@@ -228,31 +228,19 @@ async def get_cardinality(
228228
return term._cardinality
229229

230230
request = TermRequest(
231-
term=term._api_model, options=self._build_options(execution_timeout)
231+
term=term.to_dto(), options=self._build_options(execution_timeout)
232232
)
233233
response = await self._execute_with_retry(
234234
self._analyze_api.cardinality, term_request=request
235235
)
236236

237-
generated_cardinality = response.data
238-
actual_model = getattr(
239-
generated_cardinality, "actual_instance", generated_cardinality
240-
)
241-
242-
c_type = actual_model.type
243-
if c_type == "infinite":
244-
term._cardinality = Infinite()
245-
elif c_type == "bigInteger":
246-
term._cardinality = BigInteger()
247-
elif c_type == "integer":
248-
term._cardinality = Integer(actual_model.value)
249-
else:
250-
raise ValueError(f"Unknown cardinality type: {c_type}")
251-
237+
term._cardinality = Cardinality.from_dto(response.data)
252238
term._set_properties_mixin(term._cardinality)
253239
return term._cardinality
254240

255-
async def get_length(self, term: Term, execution_timeout: Optional[int] = None):
241+
async def get_length(
242+
self, term: Term, execution_timeout: Optional[int] = None
243+
) -> Length:
256244
"""Computes the minimum and maximum length of strings matched by the term.
257245
258246
Args:
@@ -266,14 +254,13 @@ async def get_length(self, term: Term, execution_timeout: Optional[int] = None):
266254
return term._length
267255

268256
request = TermRequest(
269-
term=term._api_model, options=self._build_options(execution_timeout)
257+
term=term.to_dto(), options=self._build_options(execution_timeout)
270258
)
271259
response = await self._execute_with_retry(
272260
self._analyze_api.length, term_request=request
273261
)
274262

275-
generated_length = response.data
276-
term._length = Length(min=generated_length.min, max=generated_length.max)
263+
term._length = Length.from_dto(response.data)
277264
term._set_properties_mixin(term._length)
278265
return term._length
279266

@@ -291,7 +278,7 @@ async def equivalent(
291278
bool: True if they are entirely equivalent, False otherwise.
292279
"""
293280
request = TwoTermsRequest(
294-
terms=[term1._api_model, term2._api_model],
281+
terms=[term1.to_dto(), term2.to_dto()],
295282
options=self._build_options(execution_timeout),
296283
)
297284
response = await self._execute_with_retry(
@@ -316,7 +303,7 @@ async def subset(
316303
bool: True if every string matched by `term_subset` is also matched by `term_superset`.
317304
"""
318305
request = TwoTermsRequest(
319-
terms=[term_subset._api_model, term_superset._api_model],
306+
terms=[term_subset.to_dto(), term_superset.to_dto()],
320307
options=self._build_options(execution_timeout),
321308
)
322309
response = await self._execute_with_retry(
@@ -339,7 +326,7 @@ async def is_empty(
339326
if term._empty is not None:
340327
return term._empty
341328
request = TermRequest(
342-
term=term._api_model, options=self._build_options(execution_timeout)
329+
term=term.to_dto(), options=self._build_options(execution_timeout)
343330
)
344331
response = await self._execute_with_retry(
345332
self._analyze_api.empty, term_request=request
@@ -365,7 +352,7 @@ async def is_empty_string(
365352
if term._empty_string is not None:
366353
return term._empty_string
367354
request = TermRequest(
368-
term=term._api_model, options=self._build_options(execution_timeout)
355+
term=term.to_dto(), options=self._build_options(execution_timeout)
369356
)
370357
response = await self._execute_with_retry(
371358
self._analyze_api.empty_string, term_request=request
@@ -391,7 +378,7 @@ async def is_total(
391378
if term._total is not None:
392379
return term._total
393380
request = TermRequest(
394-
term=term._api_model, options=self._build_options(execution_timeout)
381+
term=term.to_dto(), options=self._build_options(execution_timeout)
395382
)
396383
response = await self._execute_with_retry(
397384
self._analyze_api.total, term_request=request
@@ -418,7 +405,7 @@ async def get_pattern(
418405
if pattern is not None:
419406
return pattern
420407
request = TermRequest(
421-
term=term._api_model, options=self._build_options(execution_timeout)
408+
term=term.to_dto(), options=self._build_options(execution_timeout)
422409
)
423410
response = await self._execute_with_retry(
424411
self._analyze_api.pattern, term_request=request
@@ -439,7 +426,7 @@ async def get_dot(self, term: Term, execution_timeout: Optional[int] = None) ->
439426
if term._dot is not None:
440427
return term._dot
441428
request = TermRequest(
442-
term=term._api_model, options=self._build_options(execution_timeout)
429+
term=term.to_dto(), options=self._build_options(execution_timeout)
443430
)
444431
response = await self._execute_with_retry(
445432
self._analyze_api.dot, term_request=request
@@ -451,7 +438,7 @@ async def get_dot(self, term: Term, execution_timeout: Optional[int] = None) ->
451438
async def concat(
452439
self,
453440
*terms: Term,
454-
response_format: Optional[Union[ResponseFormat, str]] = None,
441+
response_format: Optional[ResponseFormat] = None,
455442
execution_timeout: Optional[int] = None,
456443
) -> Term:
457444
"""Concatenates the given terms sequentially.
@@ -465,18 +452,18 @@ async def concat(
465452
Term: A newly computed concatenated term.
466453
"""
467454
request = MultiTermsRequest(
468-
terms=[t._api_model for t in terms],
455+
terms=[t.to_dto() for t in terms],
469456
options=self._build_options(execution_timeout, response_format),
470457
)
471458
response = await self._execute_with_retry(
472459
self._compute_api.concat, multi_terms_request=request
473460
)
474-
return Term(response.data)
461+
return Term.from_dto(response.data)
475462

476463
async def intersection(
477464
self,
478465
*terms: Term,
479-
response_format: Optional[Union[ResponseFormat, str]] = None,
466+
response_format: Optional[ResponseFormat] = None,
480467
execution_timeout: Optional[int] = None,
481468
) -> Term:
482469
"""Computes the intersection of the given terms.
@@ -490,18 +477,18 @@ async def intersection(
490477
Term: A term representing only strings matched by ALL provided terms.
491478
"""
492479
request = MultiTermsRequest(
493-
terms=[t._api_model for t in terms],
480+
terms=[t.to_dto() for t in terms],
494481
options=self._build_options(execution_timeout, response_format),
495482
)
496483
response = await self._execute_with_retry(
497484
self._compute_api.intersection, multi_terms_request=request
498485
)
499-
return Term(response.data)
486+
return Term.from_dto(response.data)
500487

501488
async def union(
502489
self,
503490
*terms: Term,
504-
response_format: Optional[Union[ResponseFormat, str]] = None,
491+
response_format: Optional[ResponseFormat] = None,
505492
execution_timeout: Optional[int] = None,
506493
) -> Term:
507494
"""Computes the union of the given terms.
@@ -515,19 +502,19 @@ async def union(
515502
Term: A term representing strings matched by ANY of the provided terms.
516503
"""
517504
request = MultiTermsRequest(
518-
terms=[t._api_model for t in terms],
505+
terms=[t.to_dto() for t in terms],
519506
options=self._build_options(execution_timeout, response_format),
520507
)
521508
response = await self._execute_with_retry(
522509
self._compute_api.union, multi_terms_request=request
523510
)
524-
return Term(response.data)
511+
return Term.from_dto(response.data)
525512

526513
async def difference(
527514
self,
528515
base_term: Term,
529516
excluded_term: Term,
530-
response_format: Optional[Union[ResponseFormat, str]] = None,
517+
response_format: Optional[ResponseFormat] = None,
531518
execution_timeout: Optional[int] = None,
532519
) -> Term:
533520
"""Computes the difference between the two provided terms.
@@ -542,20 +529,20 @@ async def difference(
542529
Term: A computed difference term.
543530
"""
544531
request = TwoTermsRequest(
545-
terms=[base_term._api_model, excluded_term._api_model],
532+
terms=[base_term.to_dto(), excluded_term.to_dto()],
546533
options=self._build_options(execution_timeout, response_format),
547534
)
548535
response = await self._execute_with_retry(
549536
self._compute_api.difference, two_terms_request=request
550537
)
551-
return Term(response.data)
538+
return Term.from_dto(response.data)
552539

553540
async def repeat(
554541
self,
555542
term: Term,
556543
min_val: int,
557544
max_val: Optional[int] = None,
558-
response_format: Optional[Union[ResponseFormat, str]] = None,
545+
response_format: Optional[ResponseFormat] = None,
559546
execution_timeout: Optional[int] = None,
560547
) -> Term:
561548
"""Repeats a term between a minimum and maximum number of times.
@@ -571,20 +558,20 @@ async def repeat(
571558
Term: A computed repeated term.
572559
"""
573560
request = RepeatRequest(
574-
term=term._api_model,
561+
term=term.to_dto(),
575562
min=min_val,
576563
max=max_val,
577564
options=self._build_options(execution_timeout, response_format),
578565
)
579566
response = await self._execute_with_retry(
580567
self._compute_api.repeat, repeat_request=request
581568
)
582-
return Term(response.data)
569+
return Term.from_dto(response.data)
583570

584571
async def complement(
585572
self,
586573
term: Term,
587-
response_format: Optional[Union[ResponseFormat, str]] = None,
574+
response_format: Optional[ResponseFormat] = None,
588575
execution_timeout: Optional[int] = None,
589576
) -> Term:
590577
"""Computes the complement of the given term.
@@ -598,13 +585,13 @@ async def complement(
598585
Term: The complemented term.
599586
"""
600587
request = TermRequest(
601-
term=term._api_model,
588+
term=term.to_dto(),
602589
options=self._build_options(execution_timeout, response_format),
603590
)
604591
response = await self._execute_with_retry(
605592
self._compute_api.complement, term_request=request
606593
)
607-
return Term(response.data)
594+
return Term.from_dto(response.data)
608595

609596
# --- GENERATE ---
610597
async def generate_strings(
@@ -626,10 +613,10 @@ async def generate_strings(
626613
List[str]: A list of strings that match the term.
627614
"""
628615

629-
term_to_use = term._api_model
616+
term_to_use = term.to_dto()
630617
return_stable_term = False
631618
if term._stable_term is not None:
632-
term_to_use = term._stable_term
619+
term_to_use = term._stable_term.to_dto()
633620
else:
634621
return_stable_term = True
635622

@@ -645,6 +632,6 @@ async def generate_strings(
645632
)
646633

647634
if response.data.term is not None:
648-
term._stable_term = response.data.term
635+
term._stable_term = Term.from_dto(response.data.term)
649636

650637
return response.data.strings.value

‎regexsolver/models/cardinality.py‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
from dataclasses import dataclass
2-
from typing import Optional
2+
from typing import Optional, cast
33

4+
from regexsolver.generated.models import Cardinality as GeneratedCardinality
45
from regexsolver.models.term_properties_mixin import TermPropertiesMixin
56

67

78
class Cardinality(TermPropertiesMixin):
89
"""Base class representing the number of unique strings matched by a term."""
910

10-
pass
11+
@classmethod
12+
def from_dto(cls, dto: GeneratedCardinality) -> "Cardinality":
13+
"""Converts a generated API model into a high-level Cardinality object.
14+
15+
Args:
16+
dto (GeneratedCardinality): The raw model from the generated API.
17+
18+
Returns:
19+
Cardinality: A specialized instance (Integer, BigInteger, or Infinite).
20+
21+
Raises:
22+
ValueError: If the DTO contains an unknown cardinality type.
23+
"""
24+
actual_model = getattr(dto, "actual_instance", dto)
25+
c_type = actual_model.type
26+
27+
if c_type == "infinite":
28+
return Infinite()
29+
elif c_type == "bigInteger":
30+
return BigInteger()
31+
elif c_type == "integer":
32+
return Integer(actual_model.value)
33+
else:
34+
raise ValueError(f"Unknown cardinality type: {c_type}")
1135

1236
def __repr__(self) -> str:
1337
return "<Cardinality>"

‎regexsolver/models/length.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from dataclasses import dataclass
22
from typing import Optional
33

4+
from regexsolver.generated.models import Length as GeneratedLength
45
from regexsolver.models.term_properties_mixin import TermPropertiesMixin
56

67

@@ -16,6 +17,18 @@ class Length(TermPropertiesMixin):
1617
min: Optional[int]
1718
max: Optional[int]
1819

20+
@classmethod
21+
def from_dto(cls, dto: GeneratedLength) -> "Length":
22+
"""Converts a generated API model into a high-level Length object.
23+
24+
Args:
25+
dto (GeneratedLength): The raw model from the generated API.
26+
27+
Returns:
28+
Length: A high-level instance representing the min/max limits.
29+
"""
30+
return cls(min=dto.min, max=dto.max)
31+
1932
def __repr__(self) -> str:
2033
return f"<Length: min={self.min}, max={self.max}>"
2134

0 commit comments

Comments
 (0)