All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.1.0 - 2026-08-08
The singleton RegexSolver becomes an instantiable RegexSolverClient, with AsyncRegexSolverClient beside it, every operation moves from Term onto the client, and the SDK covers the whole API rather than the seven endpoints it knew about. The API moved with it, to a new contract served under /v1, so 1.0.x no longer reaches an endpoint that exists; see Compatibility below.
RegexSolverClient(api_token, base_url=..., auto_batch=True, max_terms_per_request=None)andAsyncRegexSolverClient, taking the same arguments. Several clients, each with its own token, can exist in one process; both work as context managers and release their session onclose()/aclose(). The synchronous client drives the asynchronous one on a shared background event loop.- The operations the API gained since 1.0.3:
complement,concat,determinize,repeat,get_cardinality,get_dot,get_length,is_empty,is_empty_string,is_total,is_deterministicandget_account_limits. - Keyword options:
response_format(REGEX,FAIRorANY),deterministicandexecution_timeouton the operations that return a term;execution_timeoutalone on analyze operations anddeterminize. generate_strings(term, limit, offset, ...), which pages through the language instead of returning a fixed count from the start, takingpath_order,character_order,seed,min_length,max_lengthandcharset. Paging is only consistent over a deterministic FAIR, hencedeterminize()andis_deterministic().Term.matches(string), evaluated locally withre— anchored\A(?:...)\Z, compiled withre.DOTALL— rather than by the API. It raises on a FAIR whose pattern is not known yet, and returnsFalsefor the empty language, which the engine writes as[].- An exception hierarchy under
RegexSolverError, so a caller can catch the case it handles instead of matching on a message.ApiErrorcarriesstatus_codeandbody, and splits per status down toRegexSyntaxError,TimeoutExceededError,QuotaExceededErrorand the rest. - A rate limiter, shared by every client holding the same token: a 429 sets a deadline from
Retry-After, requests wait for it, and the operation is retried within a five-minute budget. - Automatic batching:
concat,intersectionandunionsplit a call carrying more terms than the account allows per request and fold the results back into one, each constituent request counting against the monthly quota. Disable withauto_batch=False, or lower the split withmax_terms_per_request. - A per-term cache of what the API has already returned — cardinality, length, pattern, dot, and the empty, empty-string, total and deterministic flags — so asking twice costs one request.
Term.serialize()/Term.deserialize(), round-tripping theregex=<pattern>/fair=<payload>form, plus__eq__,__hash__,get_value(),to_dto()andfrom_dto().AccountLimits,Cardinality(Integer,BigInteger,Infinite),Length,ResponseFormat,PathOrderandCharacterOrderas exported models.generate-api.sh, which regeneratesregexsolver/_generated/from the specification the API publishes athttps://api.regexsolver.com/openapi.json;.openapi-generator-ignoreprotects the hand-written files.- CI running flake8 and mypy, then the tests on Python 3.10 through 3.14, on pushes to
main, on pull requests, and before a release is published. - A
CHANGELOG.md, this file, a pull request template, and Dependabot updates.
- The HTTP layer is an
asyncioclient generated from the OpenAPI specification, onaiohttp, instead of hand-writtenrequestscalls, withregexsolver/the hand-written surface overregexsolver/_generated/. Termis an abstract base class withRegexTermandFairTermsubclasses rather than a pydantic model;Term.regex()andTerm.fair()are unchanged.Term.get_pattern()andTerm.get_fair()read the term's own value and its cache, returningNonewhen the other format has not been resolved yet. Resolving a pattern isclient.get_pattern(term).- The minimum supported Python version is 3.10, declared in
requires-python, up from 3.7. - The package is built from
pyproject.tomlalone, with the test dependencies under thetestextra. - The tests drive the clients with
unittest.mockover the generated API instead of matching URLs withrequests_mockand loading fixtures fromtests/assets/.
RegexSolver, withget_instance()andinitialize().- The operation methods on
Term:intersection(),union(),subtraction(),is_equivalent_to(),is_subset_of(),generate_strings()andget_details(). Details, along with theregexsolver.detailsmodule, which returned cardinality, length and the empty and total flags in one response.setup.py,requirements.txtandtest-requirements.txt.
RegexSolver.get_instance().initialize(token)becomesRegexSolverClient(token), and a term method becomes a client method taking the terms as arguments:term1.union(term2)isclient.union(term1, term2),is_equivalent_toisequivalent,is_subset_ofissubset,subtractionisdifference, andget_detailsisget_cardinality(),get_length(),is_empty()andis_total().ApiErrorno longer prefixes its message withThe API returned the following error:; the message text differs andstatus_codeis what to branch on.- The endpoints moved from
https://api.regexsolver.com/api/*to/v1/*, and/api/analyze/detailsis split into one/v1/analyze/*endpoint per property. 1.1.0 is the lowest version that works against the API. - The serialized
regex=/fair=form is unchanged, so a term persisted by 1.0.x deserializes.
1.0.3 - 2024-08-11
Length.minimumis optional, so a response without one is parsed instead of raising a validation error.
1.0.2 - 2024-08-10
Cardinality.valuedefaults toNone, so an infinite cardinality, which carries no value, is parsed instead of raising a validation error.
1.0.1 - 2024-08-09
- The README documents the full API.
1.0.0 - 2024-08-01
Initial release.