PythonIota 1.8.0__tar.gz → 1.9.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.
- {pythoniota-1.8.0 → pythoniota-1.9.0}/PKG-INFO +116 -12
- pythoniota-1.8.0/src/PythonIota.egg-info/PKG-INFO → pythoniota-1.9.0/README.md +642 -555
- {pythoniota-1.8.0 → pythoniota-1.9.0}/pyproject.toml +1 -1
- pythoniota-1.8.0/README.md → pythoniota-1.9.0/src/PythonIota.egg-info/PKG-INFO +659 -538
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/PythonIota.egg-info/SOURCES.txt +4 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/__init__.py +1 -1
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_argument.py +3 -2
- pythoniota-1.9.0/src/pythoniota/cli/_completion.py +222 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_formatter.py +12 -3
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_parser.py +99 -26
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_sources.py +26 -8
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/regex/_compiler.py +22 -1
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/regex/_parser.py +4 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/regex/_pattern.py +13 -5
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/regex/_vm.py +26 -8
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/sequence.py +161 -16
- pythoniota-1.9.0/tests/test_cli_groups_version.py +347 -0
- pythoniota-1.9.0/tests/test_cli_scripts.py +316 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_integration.py +1 -1
- pythoniota-1.9.0/tests/test_regex_search.py +169 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_sequence.py +2 -2
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_sequence_typing.py +50 -0
- pythoniota-1.9.0/tests/test_sequence_utilities.py +507 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_workflows.py +29 -0
- pythoniota-1.8.0/src/pythoniota/cli/_completion.py +0 -112
- {pythoniota-1.8.0 → pythoniota-1.9.0}/MANIFEST.in +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/setup.cfg +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/PythonIota.egg-info/dependency_links.txt +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/PythonIota.egg-info/top_level.txt +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/_bitflag.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/_compat.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/_safe_eval.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/__init__.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_errors.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/cli/_namespace.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/enum.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/py.typed +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/recipes.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/src/pythoniota/regex/__init__.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/__init__.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_advanced.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_bitflags.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_cli.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_cli_completion.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_cli_sources.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_compat.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_coverage_fill.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_coverage_fill2.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_coverage_fill3.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_enum.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_enum_enhanced.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_new_features.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_recipes.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_regex.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_regex_budget.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_regex_extended.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_safe_eval.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_serialization.py +0 -0
- {pythoniota-1.8.0 → pythoniota-1.9.0}/tests/test_string_enum.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PythonIota
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
4
|
Summary: A zero-dependency Python toolkit: Go-style iota enums, sequence generators, a from-scratch regex engine, and an argparse-style CLI parser
|
|
5
5
|
Author: Equinox
|
|
6
6
|
License: MIT
|
|
@@ -26,6 +26,24 @@ pip install PythonIota
|
|
|
26
26
|
|
|
27
27
|
Requires Python 3.10+.
|
|
28
28
|
|
|
29
|
+
## 1.9.0
|
|
30
|
+
|
|
31
|
+
### New features
|
|
32
|
+
|
|
33
|
+
- Regex searches skip impossible starts using a conservative literal prefix;
|
|
34
|
+
diagnostics expose the prefix and account for prefilter operations.
|
|
35
|
+
- CLI mutually exclusive groups, version output and static completion scripts for
|
|
36
|
+
Bash, Zsh and PowerShell extend the existing metadata-only completion API.
|
|
37
|
+
- Sequence pipelines add bounded `limit`, grouping, Top-K, partitioning, iterator
|
|
38
|
+
copies and combinatorics, with protection for known non-exhausting inputs.
|
|
39
|
+
|
|
40
|
+
### Fixes
|
|
41
|
+
|
|
42
|
+
- Pattern backreferences now fail explicitly instead of silently matching digits.
|
|
43
|
+
- Out-of-range regex positions are clamped to the text, matching `re` semantics.
|
|
44
|
+
- Counted nullable repetitions stop after zero-width iterations without losing
|
|
45
|
+
the preferred non-empty alternative during iteration.
|
|
46
|
+
|
|
29
47
|
## 1.8.0
|
|
30
48
|
|
|
31
49
|
### New features
|
|
@@ -294,9 +312,50 @@ with element types preserved through generic transformations. `take(n)` still
|
|
|
294
312
|
returns a list. Chunk/window sizes must be positive and are checked before consumption.
|
|
295
313
|
|
|
296
314
|
Base sequences and their `.map()` results remain reusable. Iterator pipelines
|
|
297
|
-
have no length
|
|
298
|
-
`
|
|
299
|
-
|
|
315
|
+
have no length, but expose `infinite`: `True` for known non-exhausting sources,
|
|
316
|
+
`False` for known finite sources, and `None` when unknown. Exhaustive terminals
|
|
317
|
+
reject known non-exhausting pipelines before consuming them. Filtering/distinct
|
|
318
|
+
can yield few values without ever exhausting their infinite input; these retain
|
|
319
|
+
the protection. Arbitrary generators and early-stopping `takewhile` may remain
|
|
320
|
+
unknown, so this is not a general termination detector.
|
|
321
|
+
|
|
322
|
+
Use `.limit(n)` to keep a bounded prefix chainable (`take(n)` still returns a list):
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
iota().filter(lambda x: x % 2 == 0).limit(5).sum() # 20
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`limit` bounds the number of returned elements, not the time to produce one:
|
|
329
|
+
`iota().filter(lambda x: False).limit(1)` still cannot yield a value. Short-circuit
|
|
330
|
+
operations (`first`, `find`, `any`, `all`, `take`) remain available on infinite input.
|
|
331
|
+
|
|
332
|
+
### Grouping, selection and iterator utilities
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
iota(6).group_by(lambda x: x % 2) # {0: [0, 2, 4], 1: [1, 3, 5]}
|
|
336
|
+
iota(10).top_k(3) # [9, 8, 7]
|
|
337
|
+
iota(10).top_k(3, largest=False) # [0, 1, 2]
|
|
338
|
+
iota(2).zip_longest(["a"], fillvalue="-").to_list() # [(0, 'a'), (1, '-')]
|
|
339
|
+
iota(2).product(["a", "b"]).to_list() # [(0, 'a'), (0, 'b'), (1, 'a'), (1, 'b')]
|
|
340
|
+
iota(3).permutations(2).take(3) # [(0, 1), (0, 2), (1, 0)]
|
|
341
|
+
|
|
342
|
+
odds, evens = iota(6).partition(lambda x: x % 2 == 0)
|
|
343
|
+
odds.to_list(), evens.to_list() # ([1, 3, 5], [0, 2, 4])
|
|
344
|
+
left, right = iota(3).tee()
|
|
345
|
+
left.take(2), right.to_list() # ([0, 1], [0, 1, 2])
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`group_by(key=None)` groups globally into lists, preserving key/element insertion
|
|
349
|
+
order; unlike `itertools.groupby`, equal keys need not be adjacent. `top_k` supports
|
|
350
|
+
`key=`, preserves input order for ties and keeps O(k) selection storage, but must
|
|
351
|
+
consume the entire finite input. `top_k(0)` returns immediately without consuming.
|
|
352
|
+
Neither operation can compute a global result from an infinite stream.
|
|
353
|
+
|
|
354
|
+
`partition` returns false/true branches and evaluates its predicate once per item.
|
|
355
|
+
Like `tee`, it buffers when consumers advance at different rates; that buffer can
|
|
356
|
+
grow without bound. `product` and `permutations` defer input consumption until
|
|
357
|
+
iteration, then cache their inputs like `itertools`; they reject known infinite
|
|
358
|
+
inputs and are not constant-memory streaming operations.
|
|
300
359
|
|
|
301
360
|
### Terminal operations
|
|
302
361
|
|
|
@@ -411,9 +470,10 @@ regex.findall(r"[a-z]+", "AbCdEf", regex.IGNORECASE) # ['AbCdEf']
|
|
|
411
470
|
regex.findall(r"\d+(?=px)", "10px 20em 30px") # ['10', '30'] (lookahead)
|
|
412
471
|
```
|
|
413
472
|
|
|
414
|
-
|
|
415
|
-
engine rather than a general backtracking engine.
|
|
416
|
-
|
|
473
|
+
Pattern backreferences (`\1`, `(?P=name)`) raise `RegexError`; this is an NFA-based
|
|
474
|
+
engine rather than a general backtracking engine. Replacement templates still
|
|
475
|
+
support backreferences. Patterns are text strings, not bytes. Empty matches follow
|
|
476
|
+
the iteration and splitting behavior of Python 3.10–3.13 `re`, including a non-empty
|
|
417
477
|
match immediately after an empty one at the same position.
|
|
418
478
|
|
|
419
479
|
```python
|
|
@@ -434,10 +494,16 @@ report = pattern.diagnose("aaaa!", max_steps=1000)
|
|
|
434
494
|
print(report["status"], report["steps"], report["op_counts"])
|
|
435
495
|
```
|
|
436
496
|
|
|
497
|
+
Search and iteration use a conservative mandatory literal prefix when available.
|
|
498
|
+
`explain()["literal_prefix"]` shows it; case-insensitive patterns and leading
|
|
499
|
+
branching/nullable patterns fall back to the normal VM. Existing higher-priority
|
|
500
|
+
threads keep running: the optimization does not restart the VM for each candidate.
|
|
501
|
+
|
|
437
502
|
All matching, iteration, splitting and replacement functions accept keyword-only
|
|
438
503
|
`max_steps` (nonnegative integer) and `timeout` (nonnegative seconds), defaulting
|
|
439
|
-
to no limits. A step is a bytecode analysis/visit
|
|
440
|
-
consuming states; counts are
|
|
504
|
+
to no limits. A step is a bytecode analysis/visit or one native prefix lookup
|
|
505
|
+
(`PREFILTER`), including epsilon closure and consuming states; counts are
|
|
506
|
+
implementation-specific, not a portable time unit or a per-character work bound.
|
|
441
507
|
Nested lookarounds and all matches within one call share a single budget.
|
|
442
508
|
`finditer` starts its timeout when created, including pauses between yields.
|
|
443
509
|
|
|
@@ -481,6 +547,28 @@ Bad input prints a usage line and raises `SystemExit(2)` — the same contract a
|
|
|
481
547
|
argparse, so it drops into scripts and tests unchanged. `parse_known_args`
|
|
482
548
|
returns `(namespace, extras)` instead of erroring on unknown tokens.
|
|
483
549
|
|
|
550
|
+
### Mutually exclusive options and version output
|
|
551
|
+
|
|
552
|
+
```python
|
|
553
|
+
p = cli.ArgumentParser(prog="convert")
|
|
554
|
+
mode = p.add_mutually_exclusive_group(required=True)
|
|
555
|
+
mode.add_argument("--json", action="store_true")
|
|
556
|
+
mode.add_argument("--text", action="store_true")
|
|
557
|
+
p.add_argument("--version", action="version", version="%(prog)s 1.0")
|
|
558
|
+
p.parse_args(["--json"])
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Groups accept optional arguments only. A required group needs exactly one explicit
|
|
562
|
+
member; an optional group permits zero or one. CLI, environment and configuration
|
|
563
|
+
values count as explicit, even `False` or zero; defaults and caller `Namespace`
|
|
564
|
+
values do not. CLI overrides lower sources for the same destination, not another
|
|
565
|
+
group member: CLI `--json` plus config `text=true` is a conflict. Repeating the same
|
|
566
|
+
member is allowed. Group members cannot themselves be required or share a destination.
|
|
567
|
+
|
|
568
|
+
A valid version request prints to stdout and exits with status 0 without reading
|
|
569
|
+
configuration or converting unrelated values. It bypasses missing required options
|
|
570
|
+
but still respects argument consumption, subcommand boundaries and `--`.
|
|
571
|
+
|
|
484
572
|
### Sub-commands
|
|
485
573
|
|
|
486
574
|
```python
|
|
@@ -544,9 +632,25 @@ p.complete([], "--mode=f") # ['--mode=fast']
|
|
|
544
632
|
word, then returns sorted, unique full replacement words for options, choices
|
|
545
633
|
and subcommands. It does not parse, read config/environment, call type converters,
|
|
546
634
|
execute shells or mutate parse state. Variable-length positionals are best-effort;
|
|
547
|
-
only
|
|
548
|
-
API for shells/editors: it does not install
|
|
549
|
-
perform filesystem completion.
|
|
635
|
+
only built-in collections of plain scalar choices are enumerated, not generators
|
|
636
|
+
or custom objects. This is an adapter API for shells/editors: it does not install
|
|
637
|
+
shell hooks, quote candidates or perform filesystem completion.
|
|
638
|
+
|
|
639
|
+
### Static shell completion scripts
|
|
640
|
+
|
|
641
|
+
```python
|
|
642
|
+
script = p.completion_script("bash", command="convert")
|
|
643
|
+
# Also accepts "zsh" and "powershell"; save/load the returned text yourself.
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
This generates a quoted static snapshot of options, subcommands and finite scalar
|
|
647
|
+
choices. It does not run the application, read sources, call converters or change
|
|
648
|
+
shell configuration. Unlike `complete(tokens, prefix)`, the snapshot is not a
|
|
649
|
+
context-sensitive parser: it may suggest candidates from other options or commands.
|
|
650
|
+
Regenerate it after changing parser metadata. Shell metacharacters are emitted as
|
|
651
|
+
literal data, not executable fragments. Command names containing control characters
|
|
652
|
+
are rejected; such candidates are omitted. Zsh requires an initialized completion
|
|
653
|
+
system (`compinit`).
|
|
550
654
|
|
|
551
655
|
---
|
|
552
656
|
|