bracex 3.2__tar.gz → 3.2.1__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.
- {bracex-3.2 → bracex-3.2.1}/PKG-INFO +1 -1
- {bracex-3.2 → bracex-3.2.1}/bracex/__init__.py +47 -19
- {bracex-3.2 → bracex-3.2.1}/bracex/__meta__.py +1 -1
- bracex-3.2.1/docs/src/dictionary/en-custom.txt +45 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/about/changelog.md +9 -0
- {bracex-3.2 → bracex-3.2.1}/pyproject.toml +2 -3
- {bracex-3.2 → bracex-3.2.1}/tests/brace-cases.txt +48 -0
- {bracex-3.2 → bracex-3.2.1}/tests/brace-results.txt +122 -1
- {bracex-3.2 → bracex-3.2.1}/tests/test_brace.py +12 -1
- bracex-3.2.1/zensical.yml +164 -0
- {bracex-3.2 → bracex-3.2.1}/.gitignore +0 -0
- {bracex-3.2 → bracex-3.2.1}/.pyspelling.yml +0 -0
- {bracex-3.2 → bracex-3.2.1}/LICENSE.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/README.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/bracex/__main__.py +0 -0
- {bracex-3.2 → bracex-3.2.1}/bracex/py.typed +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/.snippets/abbr.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/.snippets/links.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/.snippets/refs.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/about/contributing.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/about/development.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/about/license.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/src/markdown/index.md +0 -0
- {bracex-3.2 → bracex-3.2.1}/docs/theme/announce.html +0 -0
- {bracex-3.2 → bracex-3.2.1}/hatch_build.py +0 -0
- {bracex-3.2 → bracex-3.2.1}/tests/__init__.py +0 -0
- {bracex-3.2 → bracex-3.2.1}/tests/generate.sh +0 -0
- {bracex-3.2 → bracex-3.2.1}/tests/test_main.py +0 -0
- {bracex-3.2 → bracex-3.2.1}/tests/test_versions.py +0 -0
- {bracex-3.2 → bracex-3.2.1}/tools/pycon.py +0 -0
|
@@ -33,8 +33,11 @@ __version_info__ = __meta__.__version_info__
|
|
|
33
33
|
_alpha = [chr(x) if x != 0x5c else '' for x in range(ord('A'), ord('z') + 1)]
|
|
34
34
|
_nalpha = list(reversed(_alpha))
|
|
35
35
|
|
|
36
|
-
RE_INT_ITER = re.compile(
|
|
37
|
-
|
|
36
|
+
RE_INT_ITER = re.compile(
|
|
37
|
+
r'([-+]?((?:0(?=\d))*)\d+)\.{2}([-+]?((?:0(?=\d))*)\d+)(?:\.{2}[-+]?(((?:0(?=\d))*)\d+))?(?=\})', re.ASCII
|
|
38
|
+
)
|
|
39
|
+
RE_CHR_ITER = re.compile(r'([A-Za-z])\.{2}([A-Za-z])(?:\.{2}[-+]?(((?:0(?=\d))*)\d+))?(?=\})', re.ASCII)
|
|
40
|
+
RE_SEQ_SEP = re.compile(r'\.(?!\})')
|
|
38
41
|
|
|
39
42
|
DEFAULT_LIMIT = 1000
|
|
40
43
|
|
|
@@ -241,7 +244,7 @@ class ExpandBrace:
|
|
|
241
244
|
i: StringIter,
|
|
242
245
|
depth: int,
|
|
243
246
|
ignore_end: bool = False
|
|
244
|
-
) -> tuple[list[str | Iterator[str]], int]:
|
|
247
|
+
) -> tuple[list[str | Iterator[str]], int, bool]:
|
|
245
248
|
"""
|
|
246
249
|
Get a string literal.
|
|
247
250
|
|
|
@@ -250,9 +253,12 @@ class ExpandBrace:
|
|
|
250
253
|
"""
|
|
251
254
|
|
|
252
255
|
result = [] # type: list[str | Iterator[str]]
|
|
256
|
+
word_start = 0
|
|
253
257
|
is_dollar = False
|
|
258
|
+
dollar_depth = 0
|
|
254
259
|
count = 1
|
|
255
260
|
literal = ''
|
|
261
|
+
has_seq = False
|
|
256
262
|
|
|
257
263
|
try:
|
|
258
264
|
while c:
|
|
@@ -266,7 +272,11 @@ class ExpandBrace:
|
|
|
266
272
|
elif c == '\\':
|
|
267
273
|
literal += self.get_escape(c, i)
|
|
268
274
|
|
|
269
|
-
elif
|
|
275
|
+
elif (ignore_brace and c == '{') or (dollar_depth and c == '}'):
|
|
276
|
+
literal += c
|
|
277
|
+
dollar_depth += 1 if c == '{' else -1
|
|
278
|
+
|
|
279
|
+
elif c == '{':
|
|
270
280
|
|
|
271
281
|
if literal:
|
|
272
282
|
result.append(literal)
|
|
@@ -274,7 +284,10 @@ class ExpandBrace:
|
|
|
274
284
|
|
|
275
285
|
# Try and get the group
|
|
276
286
|
try:
|
|
277
|
-
seq, scount = self.get_sequence(next(i), i, depth + 1)
|
|
287
|
+
seq, scount, expanded = self.get_sequence(next(i), i, depth + 1, word_start)
|
|
288
|
+
if expanded:
|
|
289
|
+
# Bash expands each postamble as a new word.
|
|
290
|
+
word_start = i.index
|
|
278
291
|
count *= scount
|
|
279
292
|
result.append(seq)
|
|
280
293
|
except StopIteration:
|
|
@@ -283,7 +296,7 @@ class ExpandBrace:
|
|
|
283
296
|
literal += c
|
|
284
297
|
raise
|
|
285
298
|
|
|
286
|
-
elif self.is_expanding() and (c == ',' or (c == '}' and not ignore_end)):
|
|
299
|
+
elif self.is_expanding() and not dollar_depth and (c == ',' or (c == '}' and not ignore_end)):
|
|
287
300
|
# We are Expanding within a group and found a group delimiter
|
|
288
301
|
# Return what we gathered before the group delimiters.
|
|
289
302
|
|
|
@@ -294,6 +307,14 @@ class ExpandBrace:
|
|
|
294
307
|
|
|
295
308
|
i.rewind(1)
|
|
296
309
|
break
|
|
310
|
+
|
|
311
|
+
elif not dollar_depth and c == '.' and i.match(RE_SEQ_SEP):
|
|
312
|
+
# Bash counts `..` like a comma when looking for the `}` that ends a top level group,
|
|
313
|
+
# unless `}` follows it, so the next `}` can end the group.
|
|
314
|
+
ignore_end = False
|
|
315
|
+
has_seq = True
|
|
316
|
+
literal += '..'
|
|
317
|
+
|
|
297
318
|
else:
|
|
298
319
|
literal += c
|
|
299
320
|
|
|
@@ -303,9 +324,9 @@ class ExpandBrace:
|
|
|
303
324
|
if literal:
|
|
304
325
|
result.append(literal)
|
|
305
326
|
|
|
306
|
-
return result, self.account(count)
|
|
327
|
+
return result, self.account(count), has_seq
|
|
307
328
|
|
|
308
|
-
def get_sequence(self, c: str, i: StringIter, depth: int) -> tuple[Iterator[str], int]:
|
|
329
|
+
def get_sequence(self, c: str, i: StringIter, depth: int, word_start: int) -> tuple[Iterator[str], int, bool]:
|
|
309
330
|
"""
|
|
310
331
|
Get the sequence.
|
|
311
332
|
|
|
@@ -316,6 +337,7 @@ class ExpandBrace:
|
|
|
316
337
|
result = [] # type: list[str | Iterator[str] | Iterable[str | Iterator[str]]]
|
|
317
338
|
release = self.set_expanding()
|
|
318
339
|
has_comma = False # Used to indicate validity of group (`{1..2}` are an exception).
|
|
340
|
+
has_seq = False # Used to indicate a top level `..` that lets the next `}` end the group.
|
|
319
341
|
is_empty = True # Tracks whether the current slot is empty `{slot,slot,slot}`.
|
|
320
342
|
counts = []
|
|
321
343
|
|
|
@@ -325,15 +347,15 @@ class ExpandBrace:
|
|
|
325
347
|
i.advance(1)
|
|
326
348
|
if item is not None:
|
|
327
349
|
self.release_expanding(release)
|
|
328
|
-
return item, self.account(count)
|
|
350
|
+
return item, self.account(count), True
|
|
329
351
|
|
|
330
352
|
try:
|
|
331
353
|
while True:
|
|
332
354
|
# Bash has some special top level logic. if `}` follows `{` but hasn't matched
|
|
333
|
-
# a group yet, keep going except when the first 2 bytes
|
|
334
|
-
# completely ignored.
|
|
335
|
-
keep_looking = depth == 1 and not has_comma
|
|
336
|
-
if (c == '}' and (not keep_looking or i.index == 2)):
|
|
355
|
+
# a group yet, keep going except when the first 2 bytes of the current
|
|
356
|
+
# postamble are `{}` which gets completely ignored.
|
|
357
|
+
keep_looking = depth == 1 and not has_comma and not has_seq
|
|
358
|
+
if (c == '}' and (not keep_looking or i.index == word_start + 2)):
|
|
337
359
|
self.release_expanding(release)
|
|
338
360
|
|
|
339
361
|
# Handle empty slot
|
|
@@ -349,7 +371,7 @@ class ExpandBrace:
|
|
|
349
371
|
for r in self.flatten(result):
|
|
350
372
|
temp = self.squash(temp, [r] if isinstance(r, str) else r)
|
|
351
373
|
temp = self.squash(temp, ['}'])
|
|
352
|
-
return temp, self.account(math.prod(counts, start=1))
|
|
374
|
+
return temp, self.account(math.prod(counts, start=1)), False
|
|
353
375
|
|
|
354
376
|
# Format return for a sequence
|
|
355
377
|
fin = iter([]) # type: Iterator[str]
|
|
@@ -369,7 +391,7 @@ class ExpandBrace:
|
|
|
369
391
|
start = e + 1
|
|
370
392
|
if start < l:
|
|
371
393
|
fin = self.chain(fin, result[start:])
|
|
372
|
-
return fin, self.account(sum(counts))
|
|
394
|
+
return fin, self.account(sum(counts)), True
|
|
373
395
|
|
|
374
396
|
elif c == ',':
|
|
375
397
|
# Must be the first element in the list.
|
|
@@ -382,7 +404,7 @@ class ExpandBrace:
|
|
|
382
404
|
|
|
383
405
|
else:
|
|
384
406
|
# Lower level: Try to find group, but give up if cannot acquire.
|
|
385
|
-
value, lcount = self.get_literals(c, i, depth, keep_looking)
|
|
407
|
+
value, lcount, has_seq = self.get_literals(c, i, depth, keep_looking)
|
|
386
408
|
counts.append(lcount)
|
|
387
409
|
if value is not None:
|
|
388
410
|
if len(value) > 1:
|
|
@@ -408,7 +430,7 @@ class ExpandBrace:
|
|
|
408
430
|
for r in self.flatten([slot]):
|
|
409
431
|
member = self.squash(member, [r] if isinstance(r, str) else r)
|
|
410
432
|
temp2 = self.squash(temp2, member)
|
|
411
|
-
return temp2, self.account(math.prod(counts, start=1))
|
|
433
|
+
return temp2, self.account(math.prod(counts, start=1)), False
|
|
412
434
|
|
|
413
435
|
def get_range(self, i: StringIter) -> tuple[Iterator[str] | None, int]:
|
|
414
436
|
"""
|
|
@@ -461,9 +483,15 @@ class ExpandBrace:
|
|
|
461
483
|
last = int64(end)
|
|
462
484
|
inc = max(1, int64(increment))
|
|
463
485
|
|
|
486
|
+
# Bash's zero-padding rule: padding is only enabled when an operand, as written,
|
|
487
|
+
# starts with `0` (or `-0`). A unary `+` sign never enables padding, but once
|
|
488
|
+
# padding is enabled by either operand, the full written width of both operands
|
|
489
|
+
# (signs included) is honored.
|
|
490
|
+
arm = bool((spad[1] - spad[0]) and not start.startswith('+'))
|
|
491
|
+
arm = arm or bool((epad[1] - epad[0]) and not end.startswith('+'))
|
|
464
492
|
spad_len = spad[1] - spad[0]
|
|
465
493
|
epad_len = epad[1] - epad[0]
|
|
466
|
-
padding = max(spad_len + len(start), epad_len + len(end)) if
|
|
494
|
+
padding = max(spad_len + len(start), epad_len + len(end)) if arm else 0
|
|
467
495
|
|
|
468
496
|
if first < last:
|
|
469
497
|
span = abs(last - first + 1)
|
|
@@ -513,7 +541,7 @@ class ExpandBrace:
|
|
|
513
541
|
"""Expand the string."""
|
|
514
542
|
|
|
515
543
|
i = StringIter(string)
|
|
516
|
-
values, _ = self.get_literals(next(i), i, 0)
|
|
544
|
+
values, _, _ = self.get_literals(next(i), i, 0)
|
|
517
545
|
|
|
518
546
|
# Squash the nested list by calculating the combinations
|
|
519
547
|
results = iter([EMPTY]) # type: Iterator[str]
|
|
@@ -193,5 +193,5 @@ def parse_version(ver: str) -> Version:
|
|
|
193
193
|
return Version(major, minor, micro, release, pre, post, dev)
|
|
194
194
|
|
|
195
195
|
|
|
196
|
-
__version_info__ = Version(3, 2,
|
|
196
|
+
__version_info__ = Version(3, 2, 1, "final")
|
|
197
197
|
__version__ = __version_info__._get_canonical()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
API
|
|
2
|
+
Accessors
|
|
3
|
+
Backport
|
|
4
|
+
Bracex
|
|
5
|
+
Changelog
|
|
6
|
+
Formatter
|
|
7
|
+
GitHub
|
|
8
|
+
Gitter
|
|
9
|
+
KiB
|
|
10
|
+
MERCHANTABILITY
|
|
11
|
+
MkDocs
|
|
12
|
+
NONINFRINGEMENT
|
|
13
|
+
NUL
|
|
14
|
+
Preprocess
|
|
15
|
+
PyPI
|
|
16
|
+
Setuptools
|
|
17
|
+
TODO
|
|
18
|
+
Tox
|
|
19
|
+
Twemoji
|
|
20
|
+
Virtualenv
|
|
21
|
+
Willmer
|
|
22
|
+
Zensical
|
|
23
|
+
accessor
|
|
24
|
+
backend
|
|
25
|
+
deprecations
|
|
26
|
+
expander
|
|
27
|
+
formatter
|
|
28
|
+
globbing
|
|
29
|
+
incrementer
|
|
30
|
+
iterables
|
|
31
|
+
linter
|
|
32
|
+
postamble
|
|
33
|
+
pre
|
|
34
|
+
prerelease
|
|
35
|
+
prereleases
|
|
36
|
+
pytest
|
|
37
|
+
regex
|
|
38
|
+
santhreal
|
|
39
|
+
stdout
|
|
40
|
+
sublicense
|
|
41
|
+
tuple
|
|
42
|
+
uncatchable
|
|
43
|
+
validator
|
|
44
|
+
wordlist
|
|
45
|
+
unary
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 3.2.1
|
|
4
|
+
|
|
5
|
+
- **FIX**: Keep numeric sequences with non-ASCII digits literal, matching Bash.
|
|
6
|
+
- **FIX**: Preserve an initial empty brace group after a valid expansion.
|
|
7
|
+
- **FIX**: Fix `${...}` inside a brace group ending the group early.
|
|
8
|
+
- **FIX**: Fix an invalid sequence such as `{1..a}` being split at a later comma instead of being kept as text.
|
|
9
|
+
- **FIX**: Fix numeric and character sequences with unary `+` signs (`{+1..3}`, `{1..+3..2}`, `{a..z..+2}`)
|
|
10
|
+
being left as literal text instead of expanded like Bash, including Bash's zero-padding rule for `+` operands.
|
|
11
|
+
|
|
3
12
|
## 3.2
|
|
4
13
|
|
|
5
14
|
- **NEW**: Drop Python 3.10 support.
|
|
@@ -40,11 +40,10 @@ include = [
|
|
|
40
40
|
"/docs/src/markdown/**/*.md",
|
|
41
41
|
"/docs/src/markdown/**/*.gif",
|
|
42
42
|
"/docs/src/markdown/**/*.png",
|
|
43
|
-
"/docs/src/
|
|
43
|
+
"/docs/src/dictionary/*.txt",
|
|
44
44
|
"/docs/theme/**/*.css",
|
|
45
45
|
"/docs/theme/**/*.js",
|
|
46
46
|
"/docs/theme/**/*.html",
|
|
47
|
-
"/requirements/*.txt",
|
|
48
47
|
"/bracex/**/*.py",
|
|
49
48
|
"/bracex/py.typed",
|
|
50
49
|
"/tests/**/*.py",
|
|
@@ -53,7 +52,7 @@ include = [
|
|
|
53
52
|
"/tools/**/*.py",
|
|
54
53
|
"/.pyspelling.yml",
|
|
55
54
|
"/.coveragerc",
|
|
56
|
-
"/
|
|
55
|
+
"/zensical.yml"
|
|
57
56
|
]
|
|
58
57
|
|
|
59
58
|
[tool.mypy]
|
|
@@ -289,3 +289,51 @@ a{b},
|
|
|
289
289
|
{a,b{c,d}
|
|
290
290
|
{a,b{
|
|
291
291
|
{2{
|
|
292
|
+
# A top level `..` that is not followed by `}` lets the next `}` end the group
|
|
293
|
+
{1..a},b}
|
|
294
|
+
{a...},c}
|
|
295
|
+
a{1..a},b}c
|
|
296
|
+
{1..a},{b,c}}
|
|
297
|
+
{1..},b}
|
|
298
|
+
# An initial empty group is literal in the postamble after a valid expansion
|
|
299
|
+
{a,b}{},c}
|
|
300
|
+
{1..2}{},c}
|
|
301
|
+
prefix{a,b}{},tail}
|
|
302
|
+
{a,b}x{},c}
|
|
303
|
+
{a,b}{}{},c}
|
|
304
|
+
{word}{},c}
|
|
305
|
+
{a{b,c}}{},d}
|
|
306
|
+
{+1..3}
|
|
307
|
+
{+1..+3}
|
|
308
|
+
{3..+1}
|
|
309
|
+
{+1..+3..2}
|
|
310
|
+
{1..+3..2}
|
|
311
|
+
{+1..+3..+2}
|
|
312
|
+
{+3..1..+2}
|
|
313
|
+
{+05..8}
|
|
314
|
+
{+005..8}
|
|
315
|
+
{05..+8}
|
|
316
|
+
{+5..+08}
|
|
317
|
+
{+05..+05}
|
|
318
|
+
{+05..08}
|
|
319
|
+
{+10..08}
|
|
320
|
+
{-05..+2}
|
|
321
|
+
{+5..05}
|
|
322
|
+
{+5..08}
|
|
323
|
+
{08..+5}
|
|
324
|
+
{+003..1}
|
|
325
|
+
{a..z..+2}
|
|
326
|
+
a{+1..2}b
|
|
327
|
+
{a,{+1..2},b}
|
|
328
|
+
{+9223372036854775806..+9223372036854775807}
|
|
329
|
+
{١..٣}
|
|
330
|
+
{1..3}
|
|
331
|
+
{1..٣}
|
|
332
|
+
{١..3}
|
|
333
|
+
{1..3..٢}
|
|
334
|
+
{a..e..٢}
|
|
335
|
+
{0١..03}
|
|
336
|
+
x{١..٣}y
|
|
337
|
+
{a,{١..٣},b}
|
|
338
|
+
{+١..+٣}
|
|
339
|
+
{-١..٣}
|
|
@@ -1262,4 +1262,125 @@ A{b,{d,e},{f,g}}Z
|
|
|
1262
1262
|
[{a,bc]
|
|
1263
1263
|
[{a,bd]><><><><{a,b{
|
|
1264
1264
|
[{a,b{]><><><><{2{
|
|
1265
|
-
[{2{]><><><><
|
|
1265
|
+
[{2{]><><><><{1..a},b}
|
|
1266
|
+
[{1..a},b}]><><><><{a...},c}
|
|
1267
|
+
[{a...},c}]><><><><a{1..a},b}c
|
|
1268
|
+
[a{1..a},b}c]><><><><{1..a},{b,c}}
|
|
1269
|
+
[{1..a},b}]
|
|
1270
|
+
[{1..a},c}]><><><><{1..},b}
|
|
1271
|
+
[1..}]
|
|
1272
|
+
[b]><><><><{a,b}{},c}
|
|
1273
|
+
[a{},c}]
|
|
1274
|
+
[b{},c}]><><><><{1..2}{},c}
|
|
1275
|
+
[1{},c}]
|
|
1276
|
+
[2{},c}]><><><><prefix{a,b}{},tail}
|
|
1277
|
+
[prefixa{},tail}]
|
|
1278
|
+
[prefixb{},tail}]><><><><{a,b}x{},c}
|
|
1279
|
+
[ax}]
|
|
1280
|
+
[axc]
|
|
1281
|
+
[bx}]
|
|
1282
|
+
[bxc]><><><><{a,b}{}{},c}
|
|
1283
|
+
[a{}}]
|
|
1284
|
+
[a{}c]
|
|
1285
|
+
[b{}}]
|
|
1286
|
+
[b{}c]><><><><{word}{},c}
|
|
1287
|
+
[word}{}]
|
|
1288
|
+
[c]><><><><{a{b,c}}{},d}
|
|
1289
|
+
[ab}{}]
|
|
1290
|
+
[ac}{}]
|
|
1291
|
+
[d]><><><><{+1..3}
|
|
1292
|
+
[1]
|
|
1293
|
+
[2]
|
|
1294
|
+
[3]><><><><{+1..+3}
|
|
1295
|
+
[1]
|
|
1296
|
+
[2]
|
|
1297
|
+
[3]><><><><{3..+1}
|
|
1298
|
+
[3]
|
|
1299
|
+
[2]
|
|
1300
|
+
[1]><><><><{+1..+3..2}
|
|
1301
|
+
[1]
|
|
1302
|
+
[3]><><><><{1..+3..2}
|
|
1303
|
+
[1]
|
|
1304
|
+
[3]><><><><{+1..+3..+2}
|
|
1305
|
+
[1]
|
|
1306
|
+
[3]><><><><{+3..1..+2}
|
|
1307
|
+
[3]
|
|
1308
|
+
[1]><><><><{+05..8}
|
|
1309
|
+
[5]
|
|
1310
|
+
[6]
|
|
1311
|
+
[7]
|
|
1312
|
+
[8]><><><><{+005..8}
|
|
1313
|
+
[5]
|
|
1314
|
+
[6]
|
|
1315
|
+
[7]
|
|
1316
|
+
[8]><><><><{05..+8}
|
|
1317
|
+
[05]
|
|
1318
|
+
[06]
|
|
1319
|
+
[07]
|
|
1320
|
+
[08]><><><><{+5..+08}
|
|
1321
|
+
[5]
|
|
1322
|
+
[6]
|
|
1323
|
+
[7]
|
|
1324
|
+
[8]><><><><{+05..+05}
|
|
1325
|
+
[5]><><><><{+05..08}
|
|
1326
|
+
[005]
|
|
1327
|
+
[006]
|
|
1328
|
+
[007]
|
|
1329
|
+
[008]><><><><{+10..08}
|
|
1330
|
+
[010]
|
|
1331
|
+
[009]
|
|
1332
|
+
[008]><><><><{-05..+2}
|
|
1333
|
+
[-05]
|
|
1334
|
+
[-04]
|
|
1335
|
+
[-03]
|
|
1336
|
+
[-02]
|
|
1337
|
+
[-01]
|
|
1338
|
+
[000]
|
|
1339
|
+
[001]
|
|
1340
|
+
[002]><><><><{+5..05}
|
|
1341
|
+
[05]><><><><{+5..08}
|
|
1342
|
+
[05]
|
|
1343
|
+
[06]
|
|
1344
|
+
[07]
|
|
1345
|
+
[08]><><><><{08..+5}
|
|
1346
|
+
[08]
|
|
1347
|
+
[07]
|
|
1348
|
+
[06]
|
|
1349
|
+
[05]><><><><{+003..1}
|
|
1350
|
+
[3]
|
|
1351
|
+
[2]
|
|
1352
|
+
[1]><><><><{a..z..+2}
|
|
1353
|
+
[a]
|
|
1354
|
+
[c]
|
|
1355
|
+
[e]
|
|
1356
|
+
[g]
|
|
1357
|
+
[i]
|
|
1358
|
+
[k]
|
|
1359
|
+
[m]
|
|
1360
|
+
[o]
|
|
1361
|
+
[q]
|
|
1362
|
+
[s]
|
|
1363
|
+
[u]
|
|
1364
|
+
[w]
|
|
1365
|
+
[y]><><><><a{+1..2}b
|
|
1366
|
+
[a1b]
|
|
1367
|
+
[a2b]><><><><{a,{+1..2},b}
|
|
1368
|
+
[a]
|
|
1369
|
+
[1]
|
|
1370
|
+
[2]
|
|
1371
|
+
[b]><><><><{+9223372036854775806..+9223372036854775807}
|
|
1372
|
+
[9223372036854775806]
|
|
1373
|
+
[9223372036854775807]><><><><{١..٣}
|
|
1374
|
+
[{١..٣}]><><><><{1..3}
|
|
1375
|
+
[{1..3}]><><><><{1..٣}
|
|
1376
|
+
[{1..٣}]><><><><{١..3}
|
|
1377
|
+
[{١..3}]><><><><{1..3..٢}
|
|
1378
|
+
[{1..3..٢}]><><><><{a..e..٢}
|
|
1379
|
+
[{a..e..٢}]><><><><{0١..03}
|
|
1380
|
+
[{0١..03}]><><><><x{١..٣}y
|
|
1381
|
+
[x{١..٣}y]><><><><{a,{١..٣},b}
|
|
1382
|
+
[a]
|
|
1383
|
+
[{١..٣}]
|
|
1384
|
+
[b]><><><><{+١..+٣}
|
|
1385
|
+
[{+١..+٣}]><><><><{-١..٣}
|
|
1386
|
+
[{-١..٣}]><><><><
|
|
@@ -50,7 +50,18 @@ class TestBraces:
|
|
|
50
50
|
dollar_cases = [
|
|
51
51
|
['${1..3}', ['${1..3}']],
|
|
52
52
|
['${a,b}${c,d}', ['${a,b}${c,d}']],
|
|
53
|
-
['x${a,b}x${c,d}x', ['x${a,b}x${c,d}x']]
|
|
53
|
+
['x${a,b}x${c,d}x', ['x${a,b}x${c,d}x']],
|
|
54
|
+
['{a,${b}}', ['a', '${b}']],
|
|
55
|
+
['{${a,b},c}', ['${a,b}', 'c']],
|
|
56
|
+
['{a,${b{c}d}e}', ['a', '${b{c}d}e']],
|
|
57
|
+
[r'{a,${b\}c}}', ['a', '${b}c}']],
|
|
58
|
+
['${x{1..2}}', ['${x1}', '${x2}']],
|
|
59
|
+
['${x{a,b}}', ['${xa}', '${xb}']],
|
|
60
|
+
['{a,${x{1..2}}}', ['a', '${x1}', '${x2}']],
|
|
61
|
+
['{a,${x{c,d}}}', ['a', '${xc}', '${xd}']],
|
|
62
|
+
['x${y{a,b}}z', ['x${ya}z', 'x${yb}z']],
|
|
63
|
+
['q{b}${b,c}z', ['q{b}${b,c}z']],
|
|
64
|
+
['{a${x:-..b}},c}', ['a${x:-..b}}', 'c']]
|
|
54
65
|
]
|
|
55
66
|
|
|
56
67
|
empty_cases = [
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
site_name: Bracex
|
|
2
|
+
site_url: https://facelessuser.github.io/bracex
|
|
3
|
+
repo_url: https://github.com/facelessuser/bracex
|
|
4
|
+
edit_uri: tree/master/docs/src/markdown
|
|
5
|
+
site_description: Python spell checker.
|
|
6
|
+
copyright: |
|
|
7
|
+
Copyright © 2018 - 2026 <a href="https://github.com/facelessuser" target="_blank" rel="noopener">Isaac Muse</a>
|
|
8
|
+
|
|
9
|
+
docs_dir: docs/src/markdown
|
|
10
|
+
theme:
|
|
11
|
+
name: zensical_pymdownx
|
|
12
|
+
custom_dir: docs/theme
|
|
13
|
+
features:
|
|
14
|
+
- announce.dismiss
|
|
15
|
+
- navigation.tabs
|
|
16
|
+
- navigation.top
|
|
17
|
+
- navigation.instant
|
|
18
|
+
- navigation.indexes
|
|
19
|
+
- navigation.path
|
|
20
|
+
- navigation.footer
|
|
21
|
+
- toc.follow
|
|
22
|
+
- content.tabs.link
|
|
23
|
+
- search.share
|
|
24
|
+
- search.highlight
|
|
25
|
+
- search.suggest
|
|
26
|
+
- content.code.copy
|
|
27
|
+
- content.tabs.link
|
|
28
|
+
- content.code.annotations
|
|
29
|
+
|
|
30
|
+
nav:
|
|
31
|
+
- Home:
|
|
32
|
+
- Usage: index.md
|
|
33
|
+
- About:
|
|
34
|
+
- Contributing & Support: about/contributing.md
|
|
35
|
+
- Development: about/development.md
|
|
36
|
+
- Changelog: about/changelog.md
|
|
37
|
+
- License: about/license.md
|
|
38
|
+
|
|
39
|
+
markdown_extensions:
|
|
40
|
+
- toc:
|
|
41
|
+
slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case: lower}}
|
|
42
|
+
permalink: ""
|
|
43
|
+
- smarty:
|
|
44
|
+
smart_quotes: false
|
|
45
|
+
- pymdownx.betterem:
|
|
46
|
+
- attr_list:
|
|
47
|
+
- tables:
|
|
48
|
+
- abbr:
|
|
49
|
+
- footnotes:
|
|
50
|
+
- md_in_html:
|
|
51
|
+
- pymdownx.superfences:
|
|
52
|
+
preserve_tabs: true
|
|
53
|
+
relaxed_headers: true
|
|
54
|
+
custom_fences:
|
|
55
|
+
- name: py
|
|
56
|
+
class: 'highlight'
|
|
57
|
+
format: !!python/object/apply:tools.pycon.py_command_formatter
|
|
58
|
+
kwds:
|
|
59
|
+
init: |
|
|
60
|
+
import bracex
|
|
61
|
+
validator: !!python/name:tools.pycon.py_command_validator
|
|
62
|
+
reset: !!python/name:tools.pycon.py_command_reset
|
|
63
|
+
- name: python
|
|
64
|
+
class: 'highlight'
|
|
65
|
+
format: !!python/object/apply:tools.pycon.py_command_formatter
|
|
66
|
+
kwds:
|
|
67
|
+
init: |
|
|
68
|
+
import bracex
|
|
69
|
+
validator: !!python/name:tools.pycon.py_command_validator
|
|
70
|
+
reset: !!python/name:tools.pycon.py_command_reset
|
|
71
|
+
- pymdownx.highlight:
|
|
72
|
+
line_spans: __codeline
|
|
73
|
+
line_anchors: __codelineno
|
|
74
|
+
anchor_linenums: True
|
|
75
|
+
- pymdownx.inlinehilite:
|
|
76
|
+
- pymdownx.magiclink:
|
|
77
|
+
repo_url_shortener: true
|
|
78
|
+
repo_url_shorthand: true
|
|
79
|
+
social_url_shorthand: true
|
|
80
|
+
user: facelessuser
|
|
81
|
+
repo: bracex
|
|
82
|
+
- pymdownx.tilde:
|
|
83
|
+
- pymdownx.caret:
|
|
84
|
+
- pymdownx.smartsymbols:
|
|
85
|
+
- pymdownx.emoji:
|
|
86
|
+
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
|
87
|
+
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
|
88
|
+
- pymdownx.escapeall:
|
|
89
|
+
hardbreak: True
|
|
90
|
+
nbsp: True
|
|
91
|
+
- pymdownx.tasklist:
|
|
92
|
+
custom_checkbox: true
|
|
93
|
+
- pymdownx.progressbar:
|
|
94
|
+
- pymdownx.striphtml:
|
|
95
|
+
- pymdownx.snippets:
|
|
96
|
+
base_path:
|
|
97
|
+
- docs/src/markdown/.snippets
|
|
98
|
+
- LICENSE.md
|
|
99
|
+
auto_append:
|
|
100
|
+
- refs.md
|
|
101
|
+
- pymdownx.keys:
|
|
102
|
+
separator: "\uff0b"
|
|
103
|
+
- pymdownx.saneheaders:
|
|
104
|
+
- pymdownx.blocks.admonition:
|
|
105
|
+
types:
|
|
106
|
+
- new
|
|
107
|
+
- settings
|
|
108
|
+
- note
|
|
109
|
+
- abstract
|
|
110
|
+
- info
|
|
111
|
+
- tip
|
|
112
|
+
- success
|
|
113
|
+
- question
|
|
114
|
+
- warning
|
|
115
|
+
- failure
|
|
116
|
+
- danger
|
|
117
|
+
- bug
|
|
118
|
+
- example
|
|
119
|
+
- quote
|
|
120
|
+
- pymdownx.blocks.details:
|
|
121
|
+
types:
|
|
122
|
+
- name: details-new
|
|
123
|
+
class: new
|
|
124
|
+
- name: details-settings
|
|
125
|
+
class: settings
|
|
126
|
+
- name: details-note
|
|
127
|
+
class: note
|
|
128
|
+
- name: details-abstract
|
|
129
|
+
class: abstract
|
|
130
|
+
- name: details-info
|
|
131
|
+
class: info
|
|
132
|
+
- name: details-tip
|
|
133
|
+
class: tip
|
|
134
|
+
- name: details-success
|
|
135
|
+
class: success
|
|
136
|
+
- name: details-question
|
|
137
|
+
class: question
|
|
138
|
+
- name: details-warning
|
|
139
|
+
class: warning
|
|
140
|
+
- name: details-failure
|
|
141
|
+
class: failure
|
|
142
|
+
- name: details-danger
|
|
143
|
+
class: danger
|
|
144
|
+
- name: details-bug
|
|
145
|
+
class: bug
|
|
146
|
+
- name: details-example
|
|
147
|
+
class: example
|
|
148
|
+
- name: details-quote
|
|
149
|
+
class: quote
|
|
150
|
+
- pymdownx.blocks.html:
|
|
151
|
+
- pymdownx.blocks.definition:
|
|
152
|
+
- pymdownx.blocks.tab:
|
|
153
|
+
alternate_style: True
|
|
154
|
+
combine_header_slug: True
|
|
155
|
+
slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case: lower}}
|
|
156
|
+
- pymdownx.quotes:
|
|
157
|
+
callouts: true
|
|
158
|
+
|
|
159
|
+
extra:
|
|
160
|
+
social:
|
|
161
|
+
- icon: fontawesome/brands/github
|
|
162
|
+
link: https://github.com/facelessuser
|
|
163
|
+
zensical_pymdownx:
|
|
164
|
+
sponsor: https://github.com/sponsors/facelessuser
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|