Skip to content

Commit b6f7e4b

Browse files
committed
add dependabot, PR template and changelog
1 parent a5161bb commit b6f7e4b

8 files changed

Lines changed: 118 additions & 13 deletions

File tree

‎.github/dependabot.yml‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: pip
4+
directory: /
5+
schedule:
6+
interval: monthly
7+
open-pull-requests-limit: 5
8+
9+
- package-ecosystem: github-actions
10+
directory: /
11+
schedule:
12+
interval: monthly

‎.github/pull_request_template.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## What this changes
2+
3+
<!-- And why. Link the issue it closes, if there is one. -->
4+
5+
## Checklist
6+
7+
- [ ] `flake8 regexsolver tests`, `mypy regexsolver` and `pytest` pass
8+
- [ ] New public items carry a docstring, and anything user-facing is in the README
9+
- [ ] A test covers the change
10+
- [ ] `CHANGELOG.md` is updated under `## [Unreleased]`
11+
- [ ] The change runs on Python 3.10, the version `requires-python` declares, or the bump is intentional and noted
12+
- [ ] `regexsolver/_generated/` is only touched by `./generate-api.sh`, once the change is live in the API's published specification

‎.github/workflows/ci.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
name: Lint & Type Check
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v4
14+
- uses: actions/checkout@v7
1515

1616
- name: Set up Python
17-
uses: actions/setup-python@v5
17+
uses: actions/setup-python@v7
1818
with:
1919
python-version: "3.12"
2020
cache: "pip"
@@ -40,10 +40,10 @@ jobs:
4040
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
4141

4242
steps:
43-
- uses: actions/checkout@v4
43+
- uses: actions/checkout@v7
4444

4545
- name: Set up Python ${{ matrix.python-version }}
46-
uses: actions/setup-python@v5
46+
uses: actions/setup-python@v7
4747
with:
4848
python-version: ${{ matrix.python-version }}
4949
cache: "pip"

‎.github/workflows/publish.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
- uses: actions/checkout@v4
14+
- uses: actions/checkout@v7
1515

1616
- name: Set up Python
17-
uses: actions/setup-python@v5
17+
uses: actions/setup-python@v7
1818
with:
1919
python-version: "3.12"
2020
cache: "pip"
@@ -33,10 +33,10 @@ jobs:
3333
runs-on: ubuntu-latest
3434

3535
steps:
36-
- uses: actions/checkout@v4
36+
- uses: actions/checkout@v7
3737

3838
- name: Set up Python
39-
uses: actions/setup-python@v5
39+
uses: actions/setup-python@v7
4040
with:
4141
python-version: "3.12"
4242

‎CHANGELOG.md‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
7+
## [1.1.0] - 2026-08-08
8+
9+
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.
10+
11+
### Added
12+
13+
- `RegexSolverClient(api_token, base_url=..., auto_batch=True, max_terms_per_request=None)` and `AsyncRegexSolverClient`, 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 on `close()` / `aclose()`. The synchronous client drives the asynchronous one on a shared background event loop.
14+
- 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_deterministic` and `get_account_limits`.
15+
- Keyword options: `response_format` (`REGEX`, `FAIR` or `ANY`), `deterministic` and `execution_timeout` on the operations that return a term; `execution_timeout` alone on analyze operations and `determinize`.
16+
- `generate_strings(term, limit, offset, ...)`, which pages through the language instead of returning a fixed count from the start, taking `path_order`, `character_order`, `seed`, `min_length`, `max_length` and `charset`. Paging is only consistent over a deterministic FAIR, hence `determinize()` and `is_deterministic()`.
17+
- `Term.matches(string)`, evaluated locally with `re` — anchored `\A(?:...)\Z`, compiled with `re.DOTALL` — rather than by the API. It raises on a FAIR whose pattern is not known yet, and returns `False` for the empty language, which the engine writes as `[]`.
18+
- An exception hierarchy under `RegexSolverError`, so a caller can catch the case it handles instead of matching on a message. `ApiError` carries `status_code` and `body`, and splits per status down to `RegexSyntaxError`, `TimeoutExceededError`, `QuotaExceededError` and the rest.
19+
- 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.
20+
- Automatic batching: `concat`, `intersection` and `union` split 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 with `auto_batch=False`, or lower the split with `max_terms_per_request`.
21+
- 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.
22+
- `Term.serialize()` / `Term.deserialize()`, round-tripping the `regex=<pattern>` / `fair=<payload>` form, plus `__eq__`, `__hash__`, `get_value()`, `to_dto()` and `from_dto()`.
23+
- `AccountLimits`, `Cardinality` (`Integer`, `BigInteger`, `Infinite`), `Length`, `ResponseFormat`, `PathOrder` and `CharacterOrder` as exported models.
24+
- `generate-api.sh`, which regenerates `regexsolver/_generated/` from the specification the API publishes at `https://api.regexsolver.com/openapi.json`; `.openapi-generator-ignore` protects the hand-written files.
25+
- 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.
26+
- A `CHANGELOG.md`, this file, a pull request template, and Dependabot updates.
27+
28+
### Changed
29+
30+
- The HTTP layer is an `asyncio` client generated from the OpenAPI specification, on `aiohttp`, instead of hand-written `requests` calls, with `regexsolver/` the hand-written surface over `regexsolver/_generated/`.
31+
- `Term` is an abstract base class with `RegexTerm` and `FairTerm` subclasses rather than a pydantic model; `Term.regex()` and `Term.fair()` are unchanged.
32+
- `Term.get_pattern()` and `Term.get_fair()` read the term's own value and its cache, returning `None` when the other format has not been resolved yet. Resolving a pattern is `client.get_pattern(term)`.
33+
- The minimum supported Python version is 3.10, declared in `requires-python`, up from 3.7.
34+
- The package is built from `pyproject.toml` alone, with the test dependencies under the `test` extra.
35+
- The tests drive the clients with `unittest.mock` over the generated API instead of matching URLs with `requests_mock` and loading fixtures from `tests/assets/`.
36+
37+
### Removed
38+
39+
- `RegexSolver`, with `get_instance()` and `initialize()`.
40+
- The operation methods on `Term`: `intersection()`, `union()`, `subtraction()`, `is_equivalent_to()`, `is_subset_of()`, `generate_strings()` and `get_details()`.
41+
- `Details`, along with the `regexsolver.details` module, which returned cardinality, length and the empty and total flags in one response.
42+
- `setup.py`, `requirements.txt` and `test-requirements.txt`.
43+
44+
### Compatibility
45+
46+
- `RegexSolver.get_instance().initialize(token)` becomes `RegexSolverClient(token)`, and a term method becomes a client method taking the terms as arguments: `term1.union(term2)` is `client.union(term1, term2)`, `is_equivalent_to` is `equivalent`, `is_subset_of` is `subset`, `subtraction` is `difference`, and `get_details` is `get_cardinality()`, `get_length()`, `is_empty()` and `is_total()`.
47+
- `ApiError` no longer prefixes its message with `The API returned the following error: `; the message text differs and `status_code` is what to branch on.
48+
- The endpoints moved from `https://api.regexsolver.com/api/*` to `/v1/*`, and `/api/analyze/details` is split into one `/v1/analyze/*` endpoint per property. 1.1.0 is the lowest version that works against the API.
49+
- The serialized `regex=` / `fair=` form is unchanged, so a term persisted by 1.0.x deserializes.
50+
51+
## [1.0.3] - 2024-08-11
52+
53+
### Fixed
54+
55+
- `Length.minimum` is optional, so a response without one is parsed instead of raising a validation error.
56+
57+
## [1.0.2] - 2024-08-10
58+
59+
### Fixed
60+
61+
- `Cardinality.value` defaults to `None`, so an infinite cardinality, which carries no value, is parsed instead of raising a validation error.
62+
63+
## [1.0.1] - 2024-08-09
64+
65+
### Changed
66+
67+
- The README documents the full API.
68+
69+
## [1.0.0] - 2024-08-01
70+
71+
Initial release.
72+
73+
[1.1.0]: https://github.com/RegexSolver/regexsolver-python/compare/v1.0.3...v1.1.0
74+
[1.0.3]: https://github.com/RegexSolver/regexsolver-python/compare/v1.0.2...v1.0.3
75+
[1.0.2]: https://github.com/RegexSolver/regexsolver-python/compare/v1.0.1...v1.0.2
76+
[1.0.1]: https://github.com/RegexSolver/regexsolver-python/compare/v1.0.0...v1.0.1
77+
[1.0.0]: https://github.com/RegexSolver/regexsolver-python/releases/tag/v1.0.0

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ try:
103103

104104
res = client.difference(term1, term2, execution_timeout=100)
105105
except TimeoutExceededError as error:
106-
print(error) # The API returned the following error: The operation took too much time.
106+
print(error) # The operation took too much time.
107107
```
108108

109109
Timeout is best effort. The exact time is not guaranteed.
@@ -151,6 +151,8 @@ Timeout is best effort. The exact time is not guaranteed.
151151

152152
*Note: For `AsyncRegexSolverClient`, this method is a coroutine and must be awaited.*
153153

154+
See [CHANGELOG.md](CHANGELOG.md) for notable changes.
155+
154156
## Cross-Language Support
155157

156158
If you want to use this library with other programming languages, we provide:

‎generate-api.sh‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#!/bin/bash
22

3-
SPEC_FILE="../m-lab/shared/openapi.yaml"
3+
# The API serves its own specification, which is the source the SDK is generated
4+
# from. Pass a path or another URL as the first argument to generate against it.
5+
SPEC="${1:-https://api.regexsolver.com/openapi.json}"
46
OUT_DIR="./"
57
PACKAGE_NAME="regexsolver._generated"
68

79
echo "Running openapi-generator-cli..."
810
openapi-generator-cli generate \
9-
-i "$SPEC_FILE" \
11+
-i "$SPEC" \
1012
-g python \
1113
-o "$OUT_DIR" \
1214
--additional-properties=packageName="$PACKAGE_NAME",library=asyncio

‎pyproject.toml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ include = ["regexsolver*"]
7171
[tool.mypy]
7272
exclude = ["regexsolver/_generated/"]
7373

74-
# Generated code is not linted or type checked; it is regenerated from
75-
# ../m-lab/shared/openapi.yaml by ./generate-api.sh.
74+
# Generated code is not linted or type checked; it is regenerated from the
75+
# specification the API publishes, by ./generate-api.sh.
7676
[[tool.mypy.overrides]]
7777
module = "regexsolver._generated.*"
7878
follow_imports = "silent"

0 commit comments

Comments
 (0)