reru 0.1.1__cp313-cp313-win_amd64.whl → 0.2.0__cp313-cp313-win_amd64.whl

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.
reru/__init__.pyi CHANGED
@@ -1,11 +1,138 @@
1
- from typing import Optional
1
+ from typing import Optional, List, Union
2
+
3
+ class SelectEngine:
4
+ Std: int
5
+ Fancy: int
2
6
 
3
7
  class Match:
4
- def start(self) -> int: ...
5
- def end(self) -> int: ...
6
- def group(self, _i: int = 0) -> str: ...
8
+ """
9
+ Represents a successful regex match.
10
+ contains the original text and span indices for the match and capture groups.
11
+ """
12
+ def start(self) -> int:
13
+ """
14
+ Returns the starting index of the match.
15
+ """
16
+
17
+ def end(self) -> int:
18
+ """
19
+ Returns the ending index of the match.
20
+ """
21
+
22
+ def group(self, ident: Union[int, str] = 0) -> str:
23
+ """
24
+ Returns the substring matched by the given group.
25
+
26
+ Args:
27
+ ident: The group index (int) or group name (str). Defaults to 0 (the whole match).
28
+
29
+ Returns:
30
+ The matched string.
31
+
32
+ Raises:
33
+ ValueError: If the group index/name is invalid or not found.
34
+ """
35
+
36
+ def groups(self) -> List[Optional[str]]:
37
+ """
38
+ Returns a list of all capture groups (excluding the specific whole-match group 0).
39
+
40
+ Returns:
41
+ A list where each element is the string matched by the group, or None if the group did not participate.
42
+ """
43
+
44
+ def lastindex(self) -> int:
45
+ """
46
+ Returns the integer index of the last matched capturing group.
47
+ """
48
+
49
+ class Pattern:
50
+ """
51
+ A compiled regular expression object.
52
+
53
+ This object holds a thread-safe reference to the underlying Rust Regex engine.
54
+ It automatically handles switching between the standard `regex` crate (O(n) time)
55
+ and `fancy-regex` (for look-arounds and back-references) based on the pattern.
56
+ """
57
+
58
+ def engine_info(self) -> str:
59
+ """
60
+ Returns the name of the underlying engine being used ('regex' or 'fancy_regex').
61
+ """
62
+
63
+ def group_names(self) -> List[str]:
64
+ """
65
+ Returns a list of named capture groups defined in the pattern.
66
+ """
67
+
68
+ def is_match(self, text: str) -> bool:
69
+ """
70
+ Checks if the pattern matches the string at the beginning.
71
+
72
+ This is faster than `match()` as it returns a boolean without allocating a Match object.
73
+
74
+ Returns:
75
+ True if the pattern matches at the start of `text`.
76
+ """
77
+ def is_search(self, text: str) -> bool:
78
+ """
79
+ Checks if the pattern matches anywhere in the string.
80
+
81
+ This is faster than `search()` as it returns a boolean without allocating a Match object.
82
+
83
+ Returns:
84
+ True if the pattern is found anywhere in `text`.
85
+ """
86
+
87
+ def match(self, text: str) -> Optional[Match]:
88
+ """
89
+ Attempts to match the pattern at the beginning of the string.
90
+
91
+ Returns:
92
+ A Match object if found, otherwise None.
93
+ """
94
+ def search(self, text: str) -> Optional[Match]:
95
+ """
96
+ Searches for the pattern anywhere in the string.
97
+
98
+ Returns:
99
+ A Match object if found, otherwise None.
100
+ """
101
+ def find(self, text: str) -> Optional[Match]:
102
+ """
103
+ Finds the first occurrence of the pattern in the string.
104
+
105
+ Returns:
106
+ A Match object if found, otherwise None.
107
+ """
108
+ def findall(self, text: str) -> List[str]:
109
+ """
110
+ Finds all non-overlapping occurrences of the pattern in the string.
111
+ """
112
+
113
+ def sub(self, repl: str, text: str) -> str:
114
+ """
115
+ Return the string obtained by replacing the leftmost non-overlapping occurrences
116
+ of the pattern in string by the replacement `repl`.
117
+
118
+ Args:
119
+ repl: The replacement string.
120
+ text: The input string to perform replacements on.
121
+ Returns:
122
+ The modified string with replacements.
123
+ """
124
+
125
+ @staticmethod
126
+ def escape(text: str) -> str:
127
+ """
128
+ Escape special characters in a string.
129
+ """
130
+
7
131
 
8
132
  class ReConfig:
133
+ """
134
+ Configuration options for compiling a regex pattern.
135
+ """
9
136
  case_insensitive: bool
10
137
  ignore_whitespace: bool
11
138
  multiline: bool
@@ -15,11 +142,129 @@ class ReConfig:
15
142
  backtrack_limit: Optional[int]
16
143
 
17
144
  def __init__(self,
18
- case_insensitive: bool, ignore_whitespace: bool, multiline: bool, unicode_mode: bool,
19
- size_limit: Optional[int], dfa_size_limit: int, backtrack_limit: Optional[int]
20
- ) -> None: ...
145
+ case_insensitive: bool = False,
146
+ ignore_whitespace: bool = False,
147
+ multiline: bool = False,
148
+ unicode_mode: bool = False,
149
+ size_limit: Optional[int] = None,
150
+ dfa_size_limit: int = 10_000_000,
151
+ backtrack_limit: Optional[int] = None
152
+ ) -> None:
153
+ """
154
+ Args:
155
+ case_insensitive: Enable case-insensitive matching.
156
+ ignore_whitespace: Allow whitespace and comments in pattern.
157
+ multiline: ^ and $ match start/end of line.
158
+ unicode_mode: Enable Unicode support.
159
+ size_limit: Limit the size of the compiled regex.
160
+ dfa_size_limit: Limit the size of the DFA graph (std engine only).
161
+ backtrack_limit: Limit the backtrack stack (fancy engine only).
162
+ """
163
+
164
+
165
+ def compile(pattern: str, config: Optional[ReConfig] = None) -> Pattern:
166
+ """
167
+ Compile a regular expression pattern into a Pattern object.
168
+
169
+ This function utilizes a thread-safe cache. If the pattern (and config)
170
+ has been seen before, a cached Pattern is returned immediately.
171
+
172
+ Args:
173
+ pattern: The regex string.
174
+ config: Optional configuration object.
175
+
176
+ Returns:
177
+ A compiled Pattern object.
178
+ """
179
+
180
+ def compile_custom(
181
+ pattern: str,
182
+ config: Optional[ReConfig] = None,
183
+ select_engine: Optional[SelectEngine] = None
184
+ ) -> Pattern:
185
+ """
186
+ Compile a regex pattern, forcing a specific underlying engine.
187
+
188
+ Args:
189
+ pattern: The regex string.
190
+ config: Optional configuration.
191
+ select_engine: Force usage of 'Std' (Rust Regex) or 'Fancy' (FancyRegex).
192
+ If None, auto-detection is used.
193
+ """
194
+
195
+ def is_match(pattern: str, text: str, config: Optional[ReConfig] = None) -> bool:
196
+ """
197
+ Checks if the pattern matches the string at the beginning.
198
+
199
+ This is faster than `match()` as it returns a boolean without allocating a Match object.
200
+
201
+ Args:
202
+ pattern: The regex string.
203
+ text: The input string to match against.
204
+ config: Optional configuration.
205
+ Returns:
206
+ True if the pattern matches at the start of `text`.
207
+ """
208
+ def is_search(pattern: str, text: str, config: Optional[ReConfig] = None) -> bool:
209
+ """
210
+ Checks if the pattern matches anywhere in the string.
211
+
212
+ This is faster than `search()` as it returns a boolean without allocating a Match object.
213
+
214
+ Args:
215
+ pattern: The regex string.
216
+ text: The input string to match against.
217
+ config: Optional configuration.
218
+ Returns:
219
+ True if the pattern is found anywhere in `text`.
220
+ """
221
+
222
+ def match(pattern: str, text: str, config: Optional[ReConfig] = None) -> Optional[Match]:
223
+ """
224
+ Attempts to match the pattern at the beginning of the string.
225
+
226
+ Args:
227
+ pattern: The regex string.
228
+ text: The input string to match against.
229
+ config: Optional configuration.
230
+ Returns:
231
+ A Match object if found, otherwise None.
232
+ """
233
+
234
+ def search(pattern: str, text: str, config: Optional[ReConfig] = None) -> Optional[Match]:
235
+ """
236
+ Searches for the pattern anywhere in the string.
237
+
238
+ Args:
239
+ pattern: The regex string.
240
+ text: The input string to match against.
241
+ config: Optional configuration.
242
+ Returns:
243
+ A Match object if found, otherwise None.
244
+ """
245
+
246
+ def sub(pattern: str, repl: str, text: str, config: Optional[ReConfig] = None) -> str:
247
+ """
248
+ Return the string obtained by replacing the leftmost non-overlapping occurrences
249
+ of the pattern in string by the replacement `repl`.
250
+
251
+ Args:
252
+ pattern: The regex string.
253
+ repl: The replacement string.
254
+ text: The input string to perform replacements on.
255
+ config: Optional configuration.
256
+ Returns:
257
+ The modified string with replacements.
258
+ """
259
+
260
+ def escape(text: str) -> str:
261
+ """
262
+ Escape special characters in a string.
263
+ """
264
+
21
265
 
22
266
 
23
- class ReRu:
24
- def is_match(pattern: str, text: str, config: Optional[ReConfig] = None) -> bool: ...
25
- def search(pattern: str, text: str, config: Optional[ReConfig] = None) -> Optional[Match]: ...
267
+ __version__: str
268
+ __name__: str
269
+ __package__: str
270
+ __all__: List[str]
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reru
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: Implementation :: CPython
@@ -34,12 +34,12 @@ It combines the raw speed of Rust's linear-time regex engine with the flexibilit
34
34
  ## 🚀 Features
35
35
 
36
36
  * **Hybrid Engine Architecture**:
37
- * **Fast Path**: Uses the `regex` crate (linear time `O(n)`) for standard patterns, ensuring protection against ReDoS (Regular Expression Denial of Service).
38
- * **Feature Path**: Automatically switches to `fancy-regex` for patterns requiring look-arounds (`(?=...)`, `(?<=...)`) or backreferences (`\1`), maintaining compatibility with Python's standard regex features.
39
-
40
-
37
+ * **Fast Path**: Uses the `regex` crate (linear time `O(n)`) for standard patterns, ensuring protection against ReDoS (Regular Expression Denial of Service).
38
+ * **Feature Path**: Automatically switches to `fancy-regex` for patterns requiring look-arounds (`(?=...)`, `(?<=...)`) or backreferences (`\1`), maintaining compatibility with Python's standard regex features.
39
+ * **Global Caching**: Compilations are cached efficiently using a thread-safe `DashMap`, making repeated calls lightning fast across threads.
41
40
  * **High Performance**: Implemented purely in Rust using `pyo3` and `maturin`.
42
- * **Built-in Caching**: Compilations are cached efficiently using a concurrent `DashMap` implementation, making repeated calls lightning fast.
41
+ * **Rich API**: Supports standard methods like `match`, `search`, `findall`, and `sub`, plus named capture groups.
42
+ * **Global Caching**: Compilations are cached efficiently using a thread-safe `DashMap`, making repeated calls lightning fast across threads.
43
43
  * **Type Safe**: Includes full type hints (`.pyi`) for better IDE integration and static analysis.
44
44
  * **Cross-Platform**: Pre-built wheels available for Linux (x86_64, aarch64, armv7, musl), macOS (Intel & Apple Silicon), and Windows (x64, x86, arm64).
45
45
 
@@ -54,54 +54,89 @@ pip install reru
54
54
 
55
55
  ## 🛠 Usage
56
56
 
57
- `reru` exposes a simple API similar to Python's standard `re` module but encapsulates methods within the `ReRu` class for optimized dispatch.
57
+ `reru` exposes a simple API similar to Python's standard `re` module. Functions are available directly at the module level for optimized dispatch.
58
58
 
59
59
  ### Basic Matching and Searching
60
60
 
61
61
  ```python
62
- from reru import ReRu
62
+ import reru
63
63
 
64
64
  # Check if a pattern matches (returns bool)
65
- if ReRu.is_match(r"\d+", "The answer is 42"):
65
+ if reru.is_match(r"\d+", "The answer is 42"):
66
66
  print("It's a match!")
67
67
 
68
68
  # Search for a pattern (returns a Match object or None)
69
- match = ReRu.search(r"(\w+) world", "hello world")
69
+ match = reru.search(r"(\w+) world", "hello world")
70
70
  if match:
71
71
  print(f"Full match: {match.group()}") # "hello world"
72
72
  print(f"Start index: {match.start()}") # 0
73
73
  print(f"End index: {match.end()}") # 11
74
74
 
75
+ # Optimized usage
76
+ RE1 = reru.compile(r"\d+")
77
+ RE1.is_match("The answer is 42")
78
+ RE2 = reru.compile(r"(\w+) world")
79
+ RE2.search("hello world")
75
80
  ```
76
81
 
77
- ### Advanced Configuration
82
+ ### Named Groups and New Methods
83
+ `reru` now supports named capture groups, `findall`, and `sub` (substitution).
78
84
 
85
+
86
+
87
+ ```python
88
+ import reru
89
+
90
+ # Named Groups
91
+ match = reru.match(r"(?P<year>\d{4})-(?P<month>\d{2})", "2024-05")
92
+ if match:
93
+ print(match.group("year")) # "2024"
94
+ print(match.group(1)) # "2024"
95
+
96
+ # Find All Matches
97
+ results = reru.findall(r"\d+", "Items: 10, 20, 30")
98
+ print(results) # ['10', '20', '30']
99
+
100
+ # Substitution
101
+ text = reru.sub(r"ERROR", "CRITICAL", "System status: ERROR")
102
+ print(text) # "System status: CRITICAL"
103
+ ```
104
+
105
+ ### Advanced Configuration
79
106
  You can fine-tune the regex engine using `ReConfig`. This allows you to control case sensitivity, multiline modes, whitespace ignoring, and execution limits.
80
107
 
108
+
81
109
  ```python
82
- from reru import ReRu, ReConfig
83
-
84
- # Configure the regex engine
85
- config = ReConfig(
86
- case_insensitive=True,
87
- ignore_whitespace=False,
88
- multiline=True,
89
- unicode_mode=True,
90
- size_limit=10 * (1 << 20), # 10 MB size limit
91
- dfa_size_limit=2 * (1 << 20), # 2 MB DFA limit
92
- backtrack_limit=1_000_000 # Limit for backtracking engine
93
- )
94
-
95
- # Perform search with config
96
- match = ReRu.search(r"ERROR", "Critical error occurred", config=config)
110
+ import reru
111
+
112
+ # Named Groups
113
+ match = reru.match(r"(?P<year>\d{4})-(?P<month>\d{2})", "2024-05")
97
114
  if match:
98
- print("Found error!")
115
+ print(match.group("year")) # "2024"
116
+ print(match.group(1)) # "2024"
117
+
118
+ # Find All Matches
119
+ results = reru.findall(r"\d+", "Items: 10, 20, 30")
120
+ print(results) # ['10', '20', '30']
99
121
 
122
+ # Substitution
123
+ text = reru.sub(r"ERROR", "CRITICAL", "System status: ERROR")
124
+ print(text) # "System status: CRITICAL"
100
125
  ```
101
126
 
127
+ ### Engine Selection (Advanced)
128
+ If you need to force a specific engine (ignoring the auto-detection), you can use `compile_custom`:
129
+ ```
130
+ from reru import SelectEngine, compile_custom
131
+
132
+ # Force the Standard Rust engine (strictly linear time)
133
+ pat = compile_custom(r"\d+", select_engine=SelectEngine.Std)
134
+ ```
135
+
136
+
102
137
  ## ⚙️ How It Works
103
138
 
104
- Under the hood, `reru` inspects the byte-code of your pattern before compilation:
139
+ reru uses a "Try-Fail" fallback strategy to ensure the best balance between performance and compatibility:
105
140
 
106
141
  1. **Inspection**: It checks for "expensive" features like look-aheads, look-behinds, and backreferences.
107
142
  2. **Selection**:
@@ -0,0 +1,8 @@
1
+ reru/__init__.py,sha256=NxObr2TsGAshHvjPqEyqs6h6lYecUR7X3iDcMJqOj2w,99
2
+ reru/__init__.pyi,sha256=hkkLUlnsuaCN5D7owR0WVdgL7_GcOvJ9SBCViRh-zcs,8090
3
+ reru/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ reru/reru.cp313-win_amd64.pyd,sha256=pzWFeqZhp8DZhWrq4MLsbcSsmWgYecdlQJ86TnqRbmw,1838080
5
+ reru-0.2.0.dist-info/METADATA,sha256=Qyf_nxqc1UaZuxKg48hyeTr3v5QmAnfy3aBMylF2qQw,6301
6
+ reru-0.2.0.dist-info/WHEEL,sha256=n_BmF69IyGtioVWE9c3M_zsEfe6-xMZy1v5HCL_6qE0,97
7
+ reru-0.2.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
8
+ reru-0.2.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- reru/__init__.py,sha256=NxObr2TsGAshHvjPqEyqs6h6lYecUR7X3iDcMJqOj2w,99
2
- reru/__init__.pyi,sha256=GlGL52RKaYvlFwy-FzlfW1YBSELY_ugAuKnOBKe138U,780
3
- reru/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- reru/reru.cp313-win_amd64.pyd,sha256=DQu_duyqWx94maDn0VtQz0OilBSCm4KBNkP4wGjR3Y0,2277376
5
- reru-0.1.1.dist-info/METADATA,sha256=zCqn60q6gBTK5w4hugNP8Qvx6OtKTU3IHTszHptkn-E,5107
6
- reru-0.1.1.dist-info/WHEEL,sha256=n_BmF69IyGtioVWE9c3M_zsEfe6-xMZy1v5HCL_6qE0,97
7
- reru-0.1.1.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
8
- reru-0.1.1.dist-info/RECORD,,
File without changes