reru 0.1.2__cp314-cp314-win_amd64.whl → 0.2.0__cp314-cp314-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,17 +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
+ """
7
48
 
8
49
  class Pattern:
9
- def is_match(self, text: str) -> bool: ...
10
- def match(self, text: str) -> Optional[Match]: ...
11
- def search(self, text: str) -> Optional[Match]: ...
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
+ """
12
130
 
13
131
 
14
132
  class ReConfig:
133
+ """
134
+ Configuration options for compiling a regex pattern.
135
+ """
15
136
  case_insensitive: bool
16
137
  ignore_whitespace: bool
17
138
  multiline: bool
@@ -21,13 +142,129 @@ class ReConfig:
21
142
  backtrack_limit: Optional[int]
22
143
 
23
144
  def __init__(self,
24
- case_insensitive: bool, ignore_whitespace: bool, multiline: bool, unicode_mode: bool,
25
- size_limit: Optional[int], dfa_size_limit: int, backtrack_limit: Optional[int]
26
- ) -> 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
+
27
265
 
28
266
 
29
- class ReRu:
30
- def compile(pattern: str, config: Optional[ReConfig] = None) -> Pattern: ...
31
- def is_match(pattern: str, text: str, config: Optional[ReConfig] = None) -> bool: ...
32
- def match(pattern: str, text: str, config: Optional[ReConfig] = None) -> Optional[Match]: ...
33
- 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.2
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,64 +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
75
  # Optimized usage
76
- RE1 = ReRu.compile(r"\d+")
77
- RE1.is_match(r"\d+", "The answer is 42")
78
- RE2 = ReRu.compile(r"(\w+) world")
76
+ RE1 = reru.compile(r"\d+")
77
+ RE1.is_match("The answer is 42")
78
+ RE2 = reru.compile(r"(\w+) world")
79
79
  RE2.search("hello world")
80
80
  ```
81
81
 
82
- ### Advanced Configuration
82
+ ### Named Groups and New Methods
83
+ `reru` now supports named capture groups, `findall`, and `sub` (substitution).
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']
83
99
 
100
+ # Substitution
101
+ text = reru.sub(r"ERROR", "CRITICAL", "System status: ERROR")
102
+ print(text) # "System status: CRITICAL"
103
+ ```
104
+
105
+ ### Advanced Configuration
84
106
  You can fine-tune the regex engine using `ReConfig`. This allows you to control case sensitivity, multiline modes, whitespace ignoring, and execution limits.
85
107
 
108
+
86
109
  ```python
87
- from reru import ReRu, ReConfig
88
-
89
- # Configure the regex engine
90
- config = ReConfig(
91
- case_insensitive=True,
92
- ignore_whitespace=False,
93
- multiline=True,
94
- unicode_mode=True,
95
- size_limit=10 * (1 << 20), # 10 MB size limit
96
- dfa_size_limit=2 * (1 << 20), # 2 MB DFA limit
97
- backtrack_limit=1_000_000 # Limit for backtracking engine
98
- )
99
-
100
- # Perform search with config
101
- 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")
102
114
  if match:
103
- print("Found error!")
115
+ print(match.group("year")) # "2024"
116
+ print(match.group(1)) # "2024"
104
117
 
105
- # Or
106
- RE1 = ReRu.compile(r"ERROR", config=config)
107
- if RE1.match("Critical error occurred"):
108
- print("Found error!")
118
+ # Find All Matches
119
+ results = reru.findall(r"\d+", "Items: 10, 20, 30")
120
+ print(results) # ['10', '20', '30']
109
121
 
122
+ # Substitution
123
+ text = reru.sub(r"ERROR", "CRITICAL", "System status: ERROR")
124
+ print(text) # "System status: CRITICAL"
110
125
  ```
111
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
+
112
137
  ## ⚙️ How It Works
113
138
 
114
- 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:
115
140
 
116
141
  1. **Inspection**: It checks for "expensive" features like look-aheads, look-behinds, and backreferences.
117
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.cp314-win_amd64.pyd,sha256=tlo51Ds62xebppO20Jm6FZ1rJvX5s24oOhFliQAqppE,1836544
5
+ reru-0.2.0.dist-info/METADATA,sha256=Qyf_nxqc1UaZuxKg48hyeTr3v5QmAnfy3aBMylF2qQw,6301
6
+ reru-0.2.0.dist-info/WHEEL,sha256=TASrtxyeL-Pi7odwPBMCgR1YebCHdBFZvgqiADG_4b0,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=UEnyo7dVtdzEjcv-c7uYD99aWNwADA9E-qUuVyyJLzo,1134
3
- reru/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- reru/reru.cp314-win_amd64.pyd,sha256=9CEznaT5mn6bkZ02oM393zoY1oujYkchI-kZ3STQz1g,1759744
5
- reru-0.1.2.dist-info/METADATA,sha256=AB-anV1ip9bs6tfCHAQR1KPk5dsbpK0j70UrJ5Wn3Ww,5371
6
- reru-0.1.2.dist-info/WHEEL,sha256=TASrtxyeL-Pi7odwPBMCgR1YebCHdBFZvgqiADG_4b0,97
7
- reru-0.1.2.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
8
- reru-0.1.2.dist-info/RECORD,,
File without changes