PythonIota 1.3.0__tar.gz → 1.7.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.
Files changed (47) hide show
  1. pythoniota-1.7.1/MANIFEST.in +1 -0
  2. {pythoniota-1.3.0/src/PythonIota.egg-info → pythoniota-1.7.1}/PKG-INFO +113 -4
  3. pythoniota-1.3.0/PKG-INFO → pythoniota-1.7.1/README.md +407 -315
  4. {pythoniota-1.3.0 → pythoniota-1.7.1}/pyproject.toml +2 -2
  5. pythoniota-1.3.0/README.md → pythoniota-1.7.1/src/PythonIota.egg-info/PKG-INFO +424 -298
  6. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/PythonIota.egg-info/SOURCES.txt +19 -0
  7. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/__init__.py +5 -1
  8. pythoniota-1.7.1/src/pythoniota/cli/__init__.py +27 -0
  9. pythoniota-1.7.1/src/pythoniota/cli/_argument.py +70 -0
  10. pythoniota-1.7.1/src/pythoniota/cli/_errors.py +9 -0
  11. pythoniota-1.7.1/src/pythoniota/cli/_formatter.py +93 -0
  12. pythoniota-1.7.1/src/pythoniota/cli/_namespace.py +17 -0
  13. pythoniota-1.7.1/src/pythoniota/cli/_parser.py +321 -0
  14. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/enum.py +2 -1
  15. pythoniota-1.7.1/src/pythoniota/regex/__init__.py +66 -0
  16. pythoniota-1.7.1/src/pythoniota/regex/_compiler.py +177 -0
  17. pythoniota-1.7.1/src/pythoniota/regex/_parser.py +463 -0
  18. pythoniota-1.7.1/src/pythoniota/regex/_pattern.py +210 -0
  19. pythoniota-1.7.1/src/pythoniota/regex/_vm.py +129 -0
  20. pythoniota-1.7.1/tests/__init__.py +0 -0
  21. pythoniota-1.7.1/tests/test_cli.py +244 -0
  22. pythoniota-1.7.1/tests/test_coverage_fill.py +250 -0
  23. pythoniota-1.7.1/tests/test_coverage_fill2.py +271 -0
  24. pythoniota-1.7.1/tests/test_coverage_fill3.py +136 -0
  25. pythoniota-1.7.1/tests/test_enum_enhanced.py +191 -0
  26. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_integration.py +1 -1
  27. pythoniota-1.7.1/tests/test_regex.py +211 -0
  28. pythoniota-1.7.1/tests/test_regex_extended.py +240 -0
  29. pythoniota-1.3.0/tests/test_enum_enhanced.py +0 -89
  30. {pythoniota-1.3.0 → pythoniota-1.7.1}/setup.cfg +0 -0
  31. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/PythonIota.egg-info/dependency_links.txt +0 -0
  32. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/PythonIota.egg-info/top_level.txt +0 -0
  33. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/_bitflag.py +0 -0
  34. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/_compat.py +0 -0
  35. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/_safe_eval.py +0 -0
  36. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/recipes.py +0 -0
  37. {pythoniota-1.3.0 → pythoniota-1.7.1}/src/pythoniota/sequence.py +0 -0
  38. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_advanced.py +0 -0
  39. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_bitflags.py +0 -0
  40. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_compat.py +0 -0
  41. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_enum.py +0 -0
  42. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_new_features.py +0 -0
  43. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_recipes.py +0 -0
  44. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_safe_eval.py +0 -0
  45. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_sequence.py +0 -0
  46. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_serialization.py +0 -0
  47. {pythoniota-1.3.0 → pythoniota-1.7.1}/tests/test_string_enum.py +0 -0
@@ -0,0 +1 @@
1
+ recursive-include tests *.py
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: PythonIota
3
- Version: 1.3.0
4
- Summary: Go-style iota enumerations and flexible sequence generators for Python
3
+ Version: 1.7.1
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
7
7
  Classifier: Programming Language :: Python :: 3
@@ -17,7 +17,8 @@ Description-Content-Type: text/markdown
17
17
 
18
18
  # PythonIota
19
19
 
20
- Go-style `iota` enumerations and flexible, lazy sequence generators for Python — zero dependencies, fully typed.
20
+ A **zero-dependency Python toolkit** of from-scratch building blocks — Go-style
21
+ `iota` enumerations, lazy sequence generators, and a linear-time regex engine.
21
22
 
22
23
  ```bash
23
24
  pip install PythonIota
@@ -25,6 +26,20 @@ pip install PythonIota
25
26
 
26
27
  Requires Python 3.10+.
27
28
 
29
+ ## 1.7.1 fixes
30
+
31
+ - Full matching now considers complete alternatives instead of rejecting a
32
+ valid match after selecting a shorter branch.
33
+ - Ordered enum members now hash consistently with equal numeric values and
34
+ equal members of other enums, preserving dictionary and set lookups.
35
+
36
+ **What's inside**
37
+
38
+ - **Enums** — Go-style `iota`, bit flags, string enums (`pythoniota.IotaEnum`, ...)
39
+ - **Sequences** — lazy, chainable generators (`pythoniota.iota`)
40
+ - **Regex** — a from-scratch NFA (Pike VM) engine, no catastrophic backtracking (`pythoniota.regex`)
41
+ - **CLI** — a from-scratch `argparse`-style argument parser (`pythoniota.cli`)
42
+
28
43
  ---
29
44
 
30
45
  ## Enums
@@ -310,6 +325,100 @@ safe_eval("a * b + 1", {"a": 3, "b": 4}) # 13
310
325
 
311
326
  ---
312
327
 
328
+ ## Regex
329
+
330
+ A from-scratch regular-expression engine. Unlike Python's backtracking `re`, it
331
+ compiles the pattern to a tiny bytecode and runs it with a **Pike VM** (a
332
+ thread-list NFA simulation), so matching is linear in `len(text) × len(program)`
333
+ — pathological patterns like `(a+)+$` finish instantly instead of hanging.
334
+
335
+ ```python
336
+ from pythoniota import regex
337
+
338
+ m = regex.match(r"(\d{4})-(\d{2})-(\d{2})", "2026-08-02")
339
+ m.groups() # ('2026', '08', '02')
340
+
341
+ regex.findall(r"\w+", "hello world") # ['hello', 'world']
342
+ regex.sub(r"\s+", "_", "a b c") # 'a_b_c'
343
+ regex.split(r"[,;]\s*", "a, b; c,d") # ['a', 'b', 'c', 'd']
344
+
345
+ named = regex.search(r"(?P<user>\w+)@(?P<host>\w+)", "user@host")
346
+ named.groupdict() # {'user': 'user', 'host': 'host'}
347
+ ```
348
+
349
+ Supported: literals, `.`, `* + ?` and their lazy forms `*? +? ??`, alternation
350
+ `|`, groups `(...)` / non-capturing `(?:...)` / named `(?P<name>...)`, lookahead
351
+ `(?=...)` / `(?!...)`, fixed-width lookbehind `(?<=...)` / `(?<!...)`, conditionals
352
+ `(?(id/name)yes|no)`, character classes `[...]`, counted repeats `{m,n}`,
353
+ shorthands `\d \w \s` (and `\D \W \S`), word boundaries `\b \B`, anchors
354
+ `^ $ \A \Z`, and hex escapes `\xHH` / `\uHHHH`. Flags: `IGNORECASE`, `MULTILINE`,
355
+ `DOTALL`, `VERBOSE` (also inline `(?imsx)`). API mirrors `re`: `compile`, `match`,
356
+ `fullmatch`, `search`, `findall`, `finditer`, `sub`, `subn`, `split`, `escape`,
357
+ with `Match.group` / `groups` / `span` / `groupdict` / `expand`.
358
+
359
+ ```python
360
+ regex.findall(r"[a-z]+", "AbCdEf", regex.IGNORECASE) # ['AbCdEf']
361
+ regex.findall(r"\d+(?=px)", "10px 20em 30px") # ['10', '30'] (lookahead)
362
+ ```
363
+
364
+ Backreferences (`\1`) are intentionally *not* supported: they can't be matched
365
+ by a finite automaton in linear time — that's the price of the no-backtracking
366
+ guarantee (the same trade-off Go's `regexp` and RE2 make).
367
+
368
+ ```python
369
+ # no ReDoS: this returns in microseconds, where re takes ~13s at length 28
370
+ regex.search(r"(a+)+$", "a" * 40 + "!") # None, instantly
371
+ ```
372
+
373
+ ---
374
+
375
+ ## CLI
376
+
377
+ A faithful subset of the standard library's `argparse`, built from scratch:
378
+
379
+ ```python
380
+ from pythoniota import cli
381
+
382
+ p = cli.ArgumentParser(prog="greet", description="say hello")
383
+ p.add_argument("name")
384
+ p.add_argument("-n", "--times", type=int, default=1)
385
+ p.add_argument("-v", "--verbose", action="store_true")
386
+
387
+ args = p.parse_args(["world", "--times", "3", "-v"])
388
+ args.name, args.times, args.verbose # ('world', 3, True)
389
+ ```
390
+
391
+ Supported:
392
+
393
+ - positional & optional arguments, `nargs` (`N` / `?` / `*` / `+`)
394
+ - `type` / `choices` / `default` / `required`
395
+ - actions: `store`, `store_true`, `store_false`, `store_const`, `append`, `count`
396
+ - `--opt=value`, clustered short flags (`-abc`), the `--` end-of-options marker
397
+ - an auto-generated `-h/--help`, and sub-commands via `add_subparsers`
398
+
399
+ Bad input prints a usage line and raises `SystemExit(2)` — the same contract as
400
+ argparse, so it drops into scripts and tests unchanged. `parse_known_args`
401
+ returns `(namespace, extras)` instead of erroring on unknown tokens.
402
+
403
+ ### Sub-commands
404
+
405
+ ```python
406
+ p = cli.ArgumentParser(prog="git")
407
+ sub = p.add_subparsers(dest="cmd")
408
+
409
+ add = sub.add_parser("add", help="stage files")
410
+ add.add_argument("path")
411
+ add.add_argument("-f", "--force", action="store_true")
412
+
413
+ rm = sub.add_parser("rm", help="remove files")
414
+ rm.add_argument("path")
415
+
416
+ args = p.parse_args(["add", "README.md", "-f"])
417
+ args.cmd, args.path, args.force # ('add', 'README.md', True)
418
+ ```
419
+
420
+ ---
421
+
313
422
  ## License
314
423
 
315
424
  MIT