simplibs-regex 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simplibs_regex-0.1.0/LICENSE +21 -0
- simplibs_regex-0.1.0/PKG-INFO +298 -0
- simplibs_regex-0.1.0/README.md +271 -0
- simplibs_regex-0.1.0/pyproject.toml +57 -0
- simplibs_regex-0.1.0/setup.cfg +4 -0
- simplibs_regex-0.1.0/src/simplibs/regex/__init__.py +171 -0
- simplibs_regex-0.1.0/src/simplibs/regex/base_class/Regex.py +328 -0
- simplibs_regex-0.1.0/src/simplibs/regex/base_class/_Precedence.py +43 -0
- simplibs_regex-0.1.0/src/simplibs/regex/base_class/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/RegexPattern.py +220 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/__init__.py +16 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/_validations/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/_validations/raise_invalid_pattern_error.py +38 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/_validations/raise_regex_pattern_invalid_flags_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/compiler/_validations/raise_regex_pattern_invalid_node_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Alternation.py +106 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Conditional.py +113 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Group.py +191 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Lookaround.py +145 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Repeat.py +185 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/Sequence.py +100 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/__init__.py +31 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/__init__.py +67 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/alternation_and_sequence/__init__.py +16 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/alternation_and_sequence/raise_node_param_not_regex_error.py +30 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/alternation_and_sequence/raise_requires_at_least_one_node_error.py +30 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/__init__.py +22 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/raise_conditional_invalid_id_type_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/raise_conditional_invalid_name_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/raise_conditional_invalid_numeric_id_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/raise_conditional_no_not_regex_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/conditional/raise_conditional_yes_not_regex_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/__init__.py +28 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_atomic_and_flags_conflict_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_atomic_and_name_conflict_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_flags_off_without_flags_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_flags_require_non_capturing_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_inner_not_regex_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_name_and_flags_conflict_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_group_name_requires_capturing_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/group/raise_invalid_group_name_error.py +33 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/lookaround/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/lookaround/raise_lookaround_inner_not_regex_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/lookaround/raise_lookaround_invalid_direction_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/lookaround/raise_variable_length_lookbehind_error.py +30 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/repeat/__init__.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/repeat/raise_repeat_inner_not_regex_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/repeat/raise_repeat_invalid_mode_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/repeat/raise_repeat_max_less_than_min_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/_validations/repeat/raise_repeat_min_negative_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/enums/LookaroundDirection.py +23 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/enums/RepeatMode.py +23 -0
- simplibs_regex-0.1.0/src/simplibs/regex/containers/enums/__init__.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/Anchor.py +81 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/CharCode.py +116 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/CharacterClass.py +130 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/CharacterRange.py +94 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/CharacterType.py +77 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/GroupReference.py +94 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/Literal.py +141 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/RawPattern.py +119 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/__init__.py +34 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_helpers/__init__.py +15 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_helpers/char_class_escape.py +34 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/__init__.py +58 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/anorch/__init__.py +14 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/anorch/raise_anchor_invalid_kind_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/char_code/__init__.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/char_code/raise_char_code_invalid_kind_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/char_code/raise_char_code_invalid_named_value_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/char_code/raise_char_code_invalid_type_error.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/char_code/raise_char_code_out_of_range_error.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_class/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_class/raise_char_class_empty_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_class/raise_char_class_item_not_allowed_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_class/raise_multi_char_literal_in_char_class_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_range/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_range/raise_character_range_invalid_boundary_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_range/raise_character_range_no_standalone_pattern_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_range/raise_character_range_start_after_end_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_type/__init__.py +14 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/character_type/raise_character_type_invalid_kind_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/group_reference/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/group_reference/raise_group_reference_invalid_identifier_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/group_reference/raise_group_reference_invalid_type_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/group_reference/raise_group_reference_numeric_out_of_range_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/literal/__init__.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/literal/raise_literal_empty_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/literal/raise_literal_invalid_type_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/_validations/literal/raise_literal_not_single_char_error.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/enums/AnchorKind.py +30 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/enums/CharCodeKind.py +28 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/enums/CharacterTypeKind.py +30 -0
- simplibs_regex-0.1.0/src/simplibs/regex/elements/enums/__init__.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/flags/Flag.py +54 -0
- simplibs_regex-0.1.0/src/simplibs/regex/flags/__init__.py +16 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/__init__.py +16 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/END.py +17 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/END_STRING.py +16 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/NON_WORD_BOUNDARY.py +17 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/START.py +17 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/START_STRING.py +17 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/WORD_BOUNDARY.py +17 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/anchors/__init__.py +25 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/DIGIT.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/NON_DIGIT.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/NON_WHITESPACE.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/NON_WORD.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/WHITESPACE.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/WORD.py +18 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/character_types/__init__.py +25 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/groups/ATOMIC_GROUP.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/groups/NAMED_GROUP.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/groups/NON_CAPTURING.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/groups/__init__.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/lookaround/LOOKAHEAD.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/lookaround/LOOKBEHIND.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/lookaround/NEGATIVE_LOOKAHEAD.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/lookaround/NEGATIVE_LOOKBEHIND.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/lookaround/__init__.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/AT_LEAST.py +22 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/BETWEEN.py +25 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/EXACTLY.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/ONE_OR_MORE.py +21 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/OPTIONAL.py +19 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/ZERO_OR_MORE.py +20 -0
- simplibs_regex-0.1.0/src/simplibs/regex/presets/quantifiers/__init__.py +25 -0
- simplibs_regex-0.1.0/src/simplibs_regex.egg-info/PKG-INFO +298 -0
- simplibs_regex-0.1.0/src/simplibs_regex.egg-info/SOURCES.txt +130 -0
- simplibs_regex-0.1.0/src/simplibs_regex.egg-info/dependency_links.txt +1 -0
- simplibs_regex-0.1.0/src/simplibs_regex.egg-info/requires.txt +4 -0
- simplibs_regex-0.1.0/src/simplibs_regex.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dalibor Sova (Sudip2708)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simplibs-regex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight, immutable regular expression helper library with lazy compilation and composable pattern utilities for the simplibs ecosystem.
|
|
5
|
+
Author-email: "Dalibor Sova (Sudip2708)" <daliborsova@seznam.cz>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/simplibs/simplibs-regex
|
|
8
|
+
Project-URL: Repository, https://github.com/simplibs/simplibs-regex
|
|
9
|
+
Project-URL: Issues, https://github.com/simplibs/simplibs-regex/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/simplibs/simplibs-regex/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: regex,regexp,pattern,pattern-matching,lazy-compilation,simplibs,simplibs-regex,developer-tools
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: Text Processing :: General
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: simplibs-exception>=1.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# 🧬 `simplibs-regex`
|
|
29
|
+
|
|
30
|
+
[](https://pypi.org/project/simplibs-regex/)
|
|
31
|
+
[](https://www.python.org/downloads/)
|
|
32
|
+
[](https://github.com/simplibs/simplibs-regex/blob/main/LICENSE)
|
|
33
|
+
|
|
34
|
+
**Compose regular expressions as Python code — no regex syntax required.**
|
|
35
|
+
|
|
36
|
+
A lightweight Python library that lets you build regular expressions out of small,
|
|
37
|
+
composable `Regex` objects instead of a raw pattern string. Nodes combine with plain
|
|
38
|
+
Python operators (`+`, `|`) and constructors, each syntax *family* Python's `re`
|
|
39
|
+
supports (quantifiers, groups, lookarounds) collapses into one parameterized
|
|
40
|
+
mechanism instead of dozens of special cases, and the whole tree compiles down to a
|
|
41
|
+
real, ordinary `re.Pattern` when you're done.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from simplibs.regex.elements import Literal
|
|
45
|
+
from simplibs.regex.presets.character_types import DIGIT
|
|
46
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
47
|
+
from simplibs.regex.presets.groups import NAMED_GROUP
|
|
48
|
+
from simplibs.regex.compiler import RegexPattern
|
|
49
|
+
|
|
50
|
+
year = NAMED_GROUP(ONE_OR_MORE(DIGIT), "year")
|
|
51
|
+
pattern = Literal("born:") + Literal(" ") + year
|
|
52
|
+
|
|
53
|
+
compiled = RegexPattern(pattern)
|
|
54
|
+
compiled.search("Born: 2026 in Prague").group("year") # -> "2026"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> `simplibs-regex` builds directly on the same architectural pattern as
|
|
58
|
+
> [`simplibs-rules`](https://pypi.org/project/simplibs-rules/) (a `Rule` base class +
|
|
59
|
+
> composable containers + presets) and
|
|
60
|
+
> [`simplibs-actions`](https://pypi.org/project/simplibs-actions/) — if either of
|
|
61
|
+
> those is familiar, this library's shape will be too.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🧭 The Core Philosophy
|
|
66
|
+
|
|
67
|
+
Writing a raw regex string means holding an entire, terse, write-only syntax in your
|
|
68
|
+
head at once — precedence rules, six different group syntaxes, escape sequences that
|
|
69
|
+
mean different things inside `[...]` than outside it. `simplibs-regex` replaces that
|
|
70
|
+
string with a small tree of ordinary Python objects: each node is independently
|
|
71
|
+
named, typed, and validated, and the tree composes with `+` (concatenation) and `|`
|
|
72
|
+
(alternation) the same way arithmetic expressions do.
|
|
73
|
+
|
|
74
|
+
Every syntax *family* — not just every syntax — is represented by exactly one
|
|
75
|
+
mechanism. Fourteen quantifier spellings (`*` `+` `?` `{n}` `{n,}` `{m,n}` ×
|
|
76
|
+
greedy/lazy/possessive) become one `Repeat(min, max, mode)`. Six group spellings
|
|
77
|
+
become one `Group(capturing, name, atomic, flags, flags_off)`. Four lookaround
|
|
78
|
+
spellings become one `Lookaround(direction, negate)`. This is deliberate: the goal is
|
|
79
|
+
never to add a new class for every distinct piece of regex syntax, but to find the
|
|
80
|
+
smallest set of genuinely different *mechanisms* and expose every syntax variant as a
|
|
81
|
+
parameter or a named preset on top of one of them.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
Repeat(Literal("ab"), min=3, max=3) # -> "(?:ab){3}"
|
|
85
|
+
Group(DIGIT, name="year") # -> "(?P<year>\d)"
|
|
86
|
+
Lookaround(Literal("USD"), direction=BEHIND) # -> "(?<=USD)"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Invalid combinations are rejected the moment you try to build them — a
|
|
90
|
+
variable-length lookbehind, a `Group` that tries to be both named and flag-scoped, a
|
|
91
|
+
`CharacterClass` item that doesn't belong there — rather than compiling into
|
|
92
|
+
something that only fails later, confusingly, inside `re.compile()`.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 📦 Installation
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install simplibs-regex
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 🚀 Quick Start in 60 Seconds
|
|
105
|
+
|
|
106
|
+
### Level 1: Build a tree, get a pattern string
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from simplibs.regex.elements import Literal
|
|
110
|
+
from simplibs.regex.presets.character_types import DIGIT
|
|
111
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
112
|
+
|
|
113
|
+
phone = Literal("+1-") + ONE_OR_MORE(DIGIT)
|
|
114
|
+
phone.to_pattern() # -> "\+1\-\d+"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Level 2: Compile and use it like any `re.Pattern`
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from simplibs.regex.compiler import RegexPattern
|
|
121
|
+
|
|
122
|
+
pattern = RegexPattern(phone)
|
|
123
|
+
pattern.search("call +1-5551234") # -> a re.Match object
|
|
124
|
+
pattern.findall("+1-111 and +1-222") # -> ["111", "222"]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Level 3: Compose groups, quantifiers, and lookarounds together
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from simplibs.regex.presets.groups import NAMED_GROUP
|
|
131
|
+
from simplibs.regex.presets.lookaround import LOOKBEHIND
|
|
132
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
133
|
+
from simplibs.regex.flags.Flag import Flag
|
|
134
|
+
|
|
135
|
+
price = LOOKBEHIND(Literal("$")) + NAMED_GROUP(ONE_OR_MORE(DIGIT), "amount")
|
|
136
|
+
pattern = RegexPattern(price, flags=frozenset({Flag.MULTILINE}))
|
|
137
|
+
pattern.search("Total: $42").group("amount") # -> "42"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🛠️ Architecture & Package Structure
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
src/simplibs/regex/
|
|
146
|
+
├── base_class/ ◄── Abstract base class Regex & precedence-aware rendering
|
|
147
|
+
│ ├── Regex.py
|
|
148
|
+
│ └── _Precedence.py
|
|
149
|
+
├── compiler/ ◄── RegexPattern — the compiled, ready-to-use runtime wrapper
|
|
150
|
+
├── containers/ ◄── Nodes that combine other nodes (Sequence, Alternation,
|
|
151
|
+
│ Repeat, Group, Lookaround, Conditional)
|
|
152
|
+
├── elements/ ◄── Leaves of the tree (Literal, RawPattern, Anchor, AnyCharacter,
|
|
153
|
+
│ CharacterType, CharacterRange, CharacterClass, GroupReference, CharCode)
|
|
154
|
+
├── flags/ ◄── The Flag enum (inline & compile-time regex flags)
|
|
155
|
+
└── presets/ ◄── Ready-made instances & factory functions over containers/elements
|
|
156
|
+
(anchors, character_types, character_classes, literals, quantifiers,
|
|
157
|
+
groups, lookaround, any_character)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 🧩 The `Regex` Class
|
|
163
|
+
|
|
164
|
+
Every node in this library inherits from `Regex`. It defines the mandatory contract
|
|
165
|
+
(`to_pattern`), precedence-aware rendering, fixed-length introspection, and `+`/`|`
|
|
166
|
+
composition out of the box.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
class Regex(ABC):
|
|
170
|
+
|
|
171
|
+
@abstractmethod
|
|
172
|
+
def to_pattern(self) -> str:
|
|
173
|
+
"""Return this node's own regex fragment."""
|
|
174
|
+
raise NotImplementedError
|
|
175
|
+
|
|
176
|
+
def fixed_length(self) -> int | None:
|
|
177
|
+
"""Return this node's match width if fixed, else None."""
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
def render(self, parent_precedence: "_Precedence") -> str:
|
|
181
|
+
"""Render for embedding, wrapping in (?:...) exactly when needed."""
|
|
182
|
+
...
|
|
183
|
+
|
|
184
|
+
def __add__(self, other: "Regex") -> "Regex": ... # -> Sequence
|
|
185
|
+
def __or__(self, other: "Regex") -> "Regex": ... # -> Alternation
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
➡️ Full method-by-method reference: [README_REGEX_CLASS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_CLASS.md)
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 📖 Quick Reference
|
|
193
|
+
|
|
194
|
+
### `containers/` — Combining nodes
|
|
195
|
+
|
|
196
|
+
| Class | Description / Parameters |
|
|
197
|
+
|---------------|------------------------------------------------------------------------------------|
|
|
198
|
+
| `Sequence` | Concatenation (`*nodes`). Behind `+`. |
|
|
199
|
+
| `Alternation` | Logical OR (`*nodes`). Behind `\|`. |
|
|
200
|
+
| `Repeat` | Unifies all 14 quantifier syntaxes (`inner, min, max, mode`). |
|
|
201
|
+
| `Group` | Unifies all 6 group syntaxes (`inner, capturing, name, atomic, flags, flags_off`). |
|
|
202
|
+
| `Lookaround` | Unifies all 4 lookaround syntaxes (`inner, direction, negate`). |
|
|
203
|
+
| `Conditional` | Group-existence branching (`id_or_name, yes, no`). |
|
|
204
|
+
|
|
205
|
+
➡️ [README_REGEX_CONTAINERS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_CONTAINERS.md)
|
|
206
|
+
|
|
207
|
+
### `elements/` — Leaves of the tree
|
|
208
|
+
|
|
209
|
+
| Class | Description |
|
|
210
|
+
|------------------|------------------------------------------------------------------|
|
|
211
|
+
| `Literal` | Literal text, auto-escaped. |
|
|
212
|
+
| `RawPattern` | Escape hatch for raw regex syntax with no dedicated node yet. |
|
|
213
|
+
| `Anchor` | Zero-width position assertions (`^ $ \A \Z \z\* \b \B`). |
|
|
214
|
+
| `AnyCharacter` | The `.` wildcard. |
|
|
215
|
+
| `CharacterType` | Built-in classes (`\d \D \w \W \s \S`). |
|
|
216
|
+
| `CharacterRange` | `a-z`-style ranges — only inside `CharacterClass`. |
|
|
217
|
+
| `CharacterClass` | `[...]` / `[^...]`. |
|
|
218
|
+
| `GroupReference` | Backreferences (`\1`, `(?P=name)`). |
|
|
219
|
+
| `CharCode` | Character-code escapes (`\xFF \uFFFF \Uhhhhhhhh \N{name} \ooo`). |
|
|
220
|
+
|
|
221
|
+
*\* `\z` requires Python 3.14+; see [README_REGEX_ELEMENTS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_ELEMENTS.md#anchor).*
|
|
222
|
+
|
|
223
|
+
➡️ [README_REGEX_ELEMENTS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_ELEMENTS.md)
|
|
224
|
+
|
|
225
|
+
### `flags/` — Inline & compile-time flags
|
|
226
|
+
|
|
227
|
+
`Flag` — `ASCII`, `IGNORECASE`, `LOCALE`, `MULTILINE`, `DOTALL`, `UNICODE`,
|
|
228
|
+
`VERBOSE` — with the restrictions Python's `re` actually enforces (`LOCALE` unusable
|
|
229
|
+
with `str` patterns, only `imsx` can be turned off in a scoped group) validated at
|
|
230
|
+
construction time, not deferred to `re.compile()`.
|
|
231
|
+
|
|
232
|
+
➡️ [README_REGEX_FLAGS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_FLAGS.md)
|
|
233
|
+
|
|
234
|
+
### `compiler/` — Compiled runtime wrapper
|
|
235
|
+
|
|
236
|
+
`RegexPattern` — compiles a tree once, then exposes `search`/`match`/`fullmatch`/
|
|
237
|
+
`findall`/`finditer`/`sub`/`subn`/`split`, thin delegation to the underlying
|
|
238
|
+
`re.Pattern`.
|
|
239
|
+
|
|
240
|
+
➡️ [README_REGEX_COMPILER](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_COMPILER.md)
|
|
241
|
+
|
|
242
|
+
### `presets/` — Ready-made instances & factories
|
|
243
|
+
|
|
244
|
+
* **`anchors`**: `START`, `END`, `START_STRING`, `END_STRING`, `WORD_BOUNDARY`, `NON_WORD_BOUNDARY`
|
|
245
|
+
* **`any_character`**: `ANY`
|
|
246
|
+
* **`character_types`**: `DIGIT`, `NON_DIGIT`, `WORD`, `NON_WORD`, `WHITESPACE`, `NON_WHITESPACE`
|
|
247
|
+
* **`character_classes`**: `LOWERCASE_LETTER`, `UPPERCASE_LETTER`, `LETTER`, `ALPHANUMERIC`, `HEX_DIGIT`
|
|
248
|
+
* **`literals`**: `TAB`, `NEWLINE`, `CARRIAGE_RETURN`, `FORM_FEED`, `VERTICAL_TAB`, `BELL`, `BACKSLASH_CHAR`
|
|
249
|
+
* **`quantifiers`**: `OPTIONAL`, `ZERO_OR_MORE`, `ONE_OR_MORE`, `EXACTLY`, `AT_LEAST`, `BETWEEN`
|
|
250
|
+
* **`groups`**: `NAMED_GROUP`, `NON_CAPTURING`, `ATOMIC_GROUP`, `WITH_FLAGS`, `CASE_INSENSITIVE`, `VERBOSE_GROUP`
|
|
251
|
+
* **`lookaround`**: `LOOKAHEAD`, `NEGATIVE_LOOKAHEAD`, `LOOKBEHIND`, `NEGATIVE_LOOKBEHIND`
|
|
252
|
+
|
|
253
|
+
➡️ [README_REGEX_PRESETS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_PRESETS.md)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## ☯️ About simplibs
|
|
258
|
+
|
|
259
|
+
All libraries in the **simplibs** (Simple Libraries) ecosystem share a common
|
|
260
|
+
engineering philosophy:
|
|
261
|
+
|
|
262
|
+
* **Dyslexia-friendly:**
|
|
263
|
+
We actively minimize cognitive load. Code is atomized into small, self-contained units,
|
|
264
|
+
files are named directly after the logical task they perform, and explanations describe
|
|
265
|
+
*why* something is designed, not just *what* it is.
|
|
266
|
+
* **Programmer's Zen:**
|
|
267
|
+
Nothing should be missing, and nothing should be superfluous. We value clean execution
|
|
268
|
+
paths and robust, understandable code architectures over rushed, messy feature sets.
|
|
269
|
+
* **Defensive Style:**
|
|
270
|
+
We actively anticipate edge cases and failure modes so that only safe operational paths
|
|
271
|
+
remain. Our code is built to degrade gracefully rather than crash unexpectedly.
|
|
272
|
+
* **Minimalism:**
|
|
273
|
+
Find the most direct path to the goal in as few operational steps as possible without
|
|
274
|
+
taking shortcuts on safety, readability, or completeness.
|
|
275
|
+
* **Code as Craft:**
|
|
276
|
+
Code should be pleasant to look at, readable at a glance, and evoke structural harmony.
|
|
277
|
+
We treat software engineering as a precision trade.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### 🤝 Contributing & Community
|
|
282
|
+
|
|
283
|
+
This is an **open-source project** built with love and care. We strongly believe in
|
|
284
|
+
community collaboration and welcome any feedback, bug reports, or feature ideas!
|
|
285
|
+
|
|
286
|
+
* **Want to contribute?** Feel free to open an Issue or submit a Pull Request.
|
|
287
|
+
* **Want to get in touch?** If you'd like to discuss the project further, collaborate,
|
|
288
|
+
or just say hello, feel free to open a GitHub Issue or start a Discussion.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### 📝 License
|
|
293
|
+
|
|
294
|
+
This library is released under the **MIT License**. Build great things!
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
[▲ Back to Top](#-simplibs-regex)
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# 🧬 `simplibs-regex`
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/simplibs-regex/)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://github.com/simplibs/simplibs-regex/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
**Compose regular expressions as Python code — no regex syntax required.**
|
|
8
|
+
|
|
9
|
+
A lightweight Python library that lets you build regular expressions out of small,
|
|
10
|
+
composable `Regex` objects instead of a raw pattern string. Nodes combine with plain
|
|
11
|
+
Python operators (`+`, `|`) and constructors, each syntax *family* Python's `re`
|
|
12
|
+
supports (quantifiers, groups, lookarounds) collapses into one parameterized
|
|
13
|
+
mechanism instead of dozens of special cases, and the whole tree compiles down to a
|
|
14
|
+
real, ordinary `re.Pattern` when you're done.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from simplibs.regex.elements import Literal
|
|
18
|
+
from simplibs.regex.presets.character_types import DIGIT
|
|
19
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
20
|
+
from simplibs.regex.presets.groups import NAMED_GROUP
|
|
21
|
+
from simplibs.regex.compiler import RegexPattern
|
|
22
|
+
|
|
23
|
+
year = NAMED_GROUP(ONE_OR_MORE(DIGIT), "year")
|
|
24
|
+
pattern = Literal("born:") + Literal(" ") + year
|
|
25
|
+
|
|
26
|
+
compiled = RegexPattern(pattern)
|
|
27
|
+
compiled.search("Born: 2026 in Prague").group("year") # -> "2026"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> `simplibs-regex` builds directly on the same architectural pattern as
|
|
31
|
+
> [`simplibs-rules`](https://pypi.org/project/simplibs-rules/) (a `Rule` base class +
|
|
32
|
+
> composable containers + presets) and
|
|
33
|
+
> [`simplibs-actions`](https://pypi.org/project/simplibs-actions/) — if either of
|
|
34
|
+
> those is familiar, this library's shape will be too.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 🧭 The Core Philosophy
|
|
39
|
+
|
|
40
|
+
Writing a raw regex string means holding an entire, terse, write-only syntax in your
|
|
41
|
+
head at once — precedence rules, six different group syntaxes, escape sequences that
|
|
42
|
+
mean different things inside `[...]` than outside it. `simplibs-regex` replaces that
|
|
43
|
+
string with a small tree of ordinary Python objects: each node is independently
|
|
44
|
+
named, typed, and validated, and the tree composes with `+` (concatenation) and `|`
|
|
45
|
+
(alternation) the same way arithmetic expressions do.
|
|
46
|
+
|
|
47
|
+
Every syntax *family* — not just every syntax — is represented by exactly one
|
|
48
|
+
mechanism. Fourteen quantifier spellings (`*` `+` `?` `{n}` `{n,}` `{m,n}` ×
|
|
49
|
+
greedy/lazy/possessive) become one `Repeat(min, max, mode)`. Six group spellings
|
|
50
|
+
become one `Group(capturing, name, atomic, flags, flags_off)`. Four lookaround
|
|
51
|
+
spellings become one `Lookaround(direction, negate)`. This is deliberate: the goal is
|
|
52
|
+
never to add a new class for every distinct piece of regex syntax, but to find the
|
|
53
|
+
smallest set of genuinely different *mechanisms* and expose every syntax variant as a
|
|
54
|
+
parameter or a named preset on top of one of them.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
Repeat(Literal("ab"), min=3, max=3) # -> "(?:ab){3}"
|
|
58
|
+
Group(DIGIT, name="year") # -> "(?P<year>\d)"
|
|
59
|
+
Lookaround(Literal("USD"), direction=BEHIND) # -> "(?<=USD)"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Invalid combinations are rejected the moment you try to build them — a
|
|
63
|
+
variable-length lookbehind, a `Group` that tries to be both named and flag-scoped, a
|
|
64
|
+
`CharacterClass` item that doesn't belong there — rather than compiling into
|
|
65
|
+
something that only fails later, confusingly, inside `re.compile()`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 📦 Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install simplibs-regex
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🚀 Quick Start in 60 Seconds
|
|
78
|
+
|
|
79
|
+
### Level 1: Build a tree, get a pattern string
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from simplibs.regex.elements import Literal
|
|
83
|
+
from simplibs.regex.presets.character_types import DIGIT
|
|
84
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
85
|
+
|
|
86
|
+
phone = Literal("+1-") + ONE_OR_MORE(DIGIT)
|
|
87
|
+
phone.to_pattern() # -> "\+1\-\d+"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Level 2: Compile and use it like any `re.Pattern`
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from simplibs.regex.compiler import RegexPattern
|
|
94
|
+
|
|
95
|
+
pattern = RegexPattern(phone)
|
|
96
|
+
pattern.search("call +1-5551234") # -> a re.Match object
|
|
97
|
+
pattern.findall("+1-111 and +1-222") # -> ["111", "222"]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Level 3: Compose groups, quantifiers, and lookarounds together
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from simplibs.regex.presets.groups import NAMED_GROUP
|
|
104
|
+
from simplibs.regex.presets.lookaround import LOOKBEHIND
|
|
105
|
+
from simplibs.regex.presets.quantifiers import ONE_OR_MORE
|
|
106
|
+
from simplibs.regex.flags.Flag import Flag
|
|
107
|
+
|
|
108
|
+
price = LOOKBEHIND(Literal("$")) + NAMED_GROUP(ONE_OR_MORE(DIGIT), "amount")
|
|
109
|
+
pattern = RegexPattern(price, flags=frozenset({Flag.MULTILINE}))
|
|
110
|
+
pattern.search("Total: $42").group("amount") # -> "42"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 🛠️ Architecture & Package Structure
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
src/simplibs/regex/
|
|
119
|
+
├── base_class/ ◄── Abstract base class Regex & precedence-aware rendering
|
|
120
|
+
│ ├── Regex.py
|
|
121
|
+
│ └── _Precedence.py
|
|
122
|
+
├── compiler/ ◄── RegexPattern — the compiled, ready-to-use runtime wrapper
|
|
123
|
+
├── containers/ ◄── Nodes that combine other nodes (Sequence, Alternation,
|
|
124
|
+
│ Repeat, Group, Lookaround, Conditional)
|
|
125
|
+
├── elements/ ◄── Leaves of the tree (Literal, RawPattern, Anchor, AnyCharacter,
|
|
126
|
+
│ CharacterType, CharacterRange, CharacterClass, GroupReference, CharCode)
|
|
127
|
+
├── flags/ ◄── The Flag enum (inline & compile-time regex flags)
|
|
128
|
+
└── presets/ ◄── Ready-made instances & factory functions over containers/elements
|
|
129
|
+
(anchors, character_types, character_classes, literals, quantifiers,
|
|
130
|
+
groups, lookaround, any_character)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🧩 The `Regex` Class
|
|
136
|
+
|
|
137
|
+
Every node in this library inherits from `Regex`. It defines the mandatory contract
|
|
138
|
+
(`to_pattern`), precedence-aware rendering, fixed-length introspection, and `+`/`|`
|
|
139
|
+
composition out of the box.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
class Regex(ABC):
|
|
143
|
+
|
|
144
|
+
@abstractmethod
|
|
145
|
+
def to_pattern(self) -> str:
|
|
146
|
+
"""Return this node's own regex fragment."""
|
|
147
|
+
raise NotImplementedError
|
|
148
|
+
|
|
149
|
+
def fixed_length(self) -> int | None:
|
|
150
|
+
"""Return this node's match width if fixed, else None."""
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
def render(self, parent_precedence: "_Precedence") -> str:
|
|
154
|
+
"""Render for embedding, wrapping in (?:...) exactly when needed."""
|
|
155
|
+
...
|
|
156
|
+
|
|
157
|
+
def __add__(self, other: "Regex") -> "Regex": ... # -> Sequence
|
|
158
|
+
def __or__(self, other: "Regex") -> "Regex": ... # -> Alternation
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
➡️ Full method-by-method reference: [README_REGEX_CLASS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_CLASS.md)
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 📖 Quick Reference
|
|
166
|
+
|
|
167
|
+
### `containers/` — Combining nodes
|
|
168
|
+
|
|
169
|
+
| Class | Description / Parameters |
|
|
170
|
+
|---------------|------------------------------------------------------------------------------------|
|
|
171
|
+
| `Sequence` | Concatenation (`*nodes`). Behind `+`. |
|
|
172
|
+
| `Alternation` | Logical OR (`*nodes`). Behind `\|`. |
|
|
173
|
+
| `Repeat` | Unifies all 14 quantifier syntaxes (`inner, min, max, mode`). |
|
|
174
|
+
| `Group` | Unifies all 6 group syntaxes (`inner, capturing, name, atomic, flags, flags_off`). |
|
|
175
|
+
| `Lookaround` | Unifies all 4 lookaround syntaxes (`inner, direction, negate`). |
|
|
176
|
+
| `Conditional` | Group-existence branching (`id_or_name, yes, no`). |
|
|
177
|
+
|
|
178
|
+
➡️ [README_REGEX_CONTAINERS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_CONTAINERS.md)
|
|
179
|
+
|
|
180
|
+
### `elements/` — Leaves of the tree
|
|
181
|
+
|
|
182
|
+
| Class | Description |
|
|
183
|
+
|------------------|------------------------------------------------------------------|
|
|
184
|
+
| `Literal` | Literal text, auto-escaped. |
|
|
185
|
+
| `RawPattern` | Escape hatch for raw regex syntax with no dedicated node yet. |
|
|
186
|
+
| `Anchor` | Zero-width position assertions (`^ $ \A \Z \z\* \b \B`). |
|
|
187
|
+
| `AnyCharacter` | The `.` wildcard. |
|
|
188
|
+
| `CharacterType` | Built-in classes (`\d \D \w \W \s \S`). |
|
|
189
|
+
| `CharacterRange` | `a-z`-style ranges — only inside `CharacterClass`. |
|
|
190
|
+
| `CharacterClass` | `[...]` / `[^...]`. |
|
|
191
|
+
| `GroupReference` | Backreferences (`\1`, `(?P=name)`). |
|
|
192
|
+
| `CharCode` | Character-code escapes (`\xFF \uFFFF \Uhhhhhhhh \N{name} \ooo`). |
|
|
193
|
+
|
|
194
|
+
*\* `\z` requires Python 3.14+; see [README_REGEX_ELEMENTS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_ELEMENTS.md#anchor).*
|
|
195
|
+
|
|
196
|
+
➡️ [README_REGEX_ELEMENTS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_ELEMENTS.md)
|
|
197
|
+
|
|
198
|
+
### `flags/` — Inline & compile-time flags
|
|
199
|
+
|
|
200
|
+
`Flag` — `ASCII`, `IGNORECASE`, `LOCALE`, `MULTILINE`, `DOTALL`, `UNICODE`,
|
|
201
|
+
`VERBOSE` — with the restrictions Python's `re` actually enforces (`LOCALE` unusable
|
|
202
|
+
with `str` patterns, only `imsx` can be turned off in a scoped group) validated at
|
|
203
|
+
construction time, not deferred to `re.compile()`.
|
|
204
|
+
|
|
205
|
+
➡️ [README_REGEX_FLAGS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_FLAGS.md)
|
|
206
|
+
|
|
207
|
+
### `compiler/` — Compiled runtime wrapper
|
|
208
|
+
|
|
209
|
+
`RegexPattern` — compiles a tree once, then exposes `search`/`match`/`fullmatch`/
|
|
210
|
+
`findall`/`finditer`/`sub`/`subn`/`split`, thin delegation to the underlying
|
|
211
|
+
`re.Pattern`.
|
|
212
|
+
|
|
213
|
+
➡️ [README_REGEX_COMPILER](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_COMPILER.md)
|
|
214
|
+
|
|
215
|
+
### `presets/` — Ready-made instances & factories
|
|
216
|
+
|
|
217
|
+
* **`anchors`**: `START`, `END`, `START_STRING`, `END_STRING`, `WORD_BOUNDARY`, `NON_WORD_BOUNDARY`
|
|
218
|
+
* **`any_character`**: `ANY`
|
|
219
|
+
* **`character_types`**: `DIGIT`, `NON_DIGIT`, `WORD`, `NON_WORD`, `WHITESPACE`, `NON_WHITESPACE`
|
|
220
|
+
* **`character_classes`**: `LOWERCASE_LETTER`, `UPPERCASE_LETTER`, `LETTER`, `ALPHANUMERIC`, `HEX_DIGIT`
|
|
221
|
+
* **`literals`**: `TAB`, `NEWLINE`, `CARRIAGE_RETURN`, `FORM_FEED`, `VERTICAL_TAB`, `BELL`, `BACKSLASH_CHAR`
|
|
222
|
+
* **`quantifiers`**: `OPTIONAL`, `ZERO_OR_MORE`, `ONE_OR_MORE`, `EXACTLY`, `AT_LEAST`, `BETWEEN`
|
|
223
|
+
* **`groups`**: `NAMED_GROUP`, `NON_CAPTURING`, `ATOMIC_GROUP`, `WITH_FLAGS`, `CASE_INSENSITIVE`, `VERBOSE_GROUP`
|
|
224
|
+
* **`lookaround`**: `LOOKAHEAD`, `NEGATIVE_LOOKAHEAD`, `LOOKBEHIND`, `NEGATIVE_LOOKBEHIND`
|
|
225
|
+
|
|
226
|
+
➡️ [README_REGEX_PRESETS](https://github.com/simplibs/simplibs-regex/blob/main/docs/README_REGEX_PRESETS.md)
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## ☯️ About simplibs
|
|
231
|
+
|
|
232
|
+
All libraries in the **simplibs** (Simple Libraries) ecosystem share a common
|
|
233
|
+
engineering philosophy:
|
|
234
|
+
|
|
235
|
+
* **Dyslexia-friendly:**
|
|
236
|
+
We actively minimize cognitive load. Code is atomized into small, self-contained units,
|
|
237
|
+
files are named directly after the logical task they perform, and explanations describe
|
|
238
|
+
*why* something is designed, not just *what* it is.
|
|
239
|
+
* **Programmer's Zen:**
|
|
240
|
+
Nothing should be missing, and nothing should be superfluous. We value clean execution
|
|
241
|
+
paths and robust, understandable code architectures over rushed, messy feature sets.
|
|
242
|
+
* **Defensive Style:**
|
|
243
|
+
We actively anticipate edge cases and failure modes so that only safe operational paths
|
|
244
|
+
remain. Our code is built to degrade gracefully rather than crash unexpectedly.
|
|
245
|
+
* **Minimalism:**
|
|
246
|
+
Find the most direct path to the goal in as few operational steps as possible without
|
|
247
|
+
taking shortcuts on safety, readability, or completeness.
|
|
248
|
+
* **Code as Craft:**
|
|
249
|
+
Code should be pleasant to look at, readable at a glance, and evoke structural harmony.
|
|
250
|
+
We treat software engineering as a precision trade.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 🤝 Contributing & Community
|
|
255
|
+
|
|
256
|
+
This is an **open-source project** built with love and care. We strongly believe in
|
|
257
|
+
community collaboration and welcome any feedback, bug reports, or feature ideas!
|
|
258
|
+
|
|
259
|
+
* **Want to contribute?** Feel free to open an Issue or submit a Pull Request.
|
|
260
|
+
* **Want to get in touch?** If you'd like to discuss the project further, collaborate,
|
|
261
|
+
or just say hello, feel free to open a GitHub Issue or start a Discussion.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### 📝 License
|
|
266
|
+
|
|
267
|
+
This library is released under the **MIT License**. Build great things!
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
[▲ Back to Top](#-simplibs-regex)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "simplibs-regex"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Lightweight, immutable regular expression helper library with lazy compilation and composable pattern utilities for the simplibs ecosystem."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
keywords = [
|
|
13
|
+
"regex",
|
|
14
|
+
"regexp",
|
|
15
|
+
"pattern",
|
|
16
|
+
"pattern-matching",
|
|
17
|
+
"lazy-compilation",
|
|
18
|
+
"simplibs",
|
|
19
|
+
"simplibs-regex",
|
|
20
|
+
"developer-tools",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 3 - Alpha",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
30
|
+
"Topic :: Text Processing :: General",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"simplibs-exception>=1.0.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[project.authors]]
|
|
37
|
+
name = "Dalibor Sova (Sudip2708)"
|
|
38
|
+
email = "daliborsova@seznam.cz"
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/simplibs/simplibs-regex"
|
|
42
|
+
Repository = "https://github.com/simplibs/simplibs-regex"
|
|
43
|
+
Issues = "https://github.com/simplibs/simplibs-regex/issues"
|
|
44
|
+
Changelog = "https://github.com/simplibs/simplibs-regex/blob/main/CHANGELOG.md"
|
|
45
|
+
|
|
46
|
+
[project.optional-dependencies]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=7.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
pythonpath = ["src"]
|
|
54
|
+
addopts = "-v"
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.packages.find]
|
|
57
|
+
where = ["src"]
|