literalenum 0.1.1__py3-none-any.whl → 0.2.0__py3-none-any.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.
- literalenum/stubgen.py +44 -2
- {literalenum-0.1.1.dist-info → literalenum-0.2.0.dist-info}/METADATA +32 -4
- {literalenum-0.1.1.dist-info → literalenum-0.2.0.dist-info}/RECORD +6 -6
- {literalenum-0.1.1.dist-info → literalenum-0.2.0.dist-info}/WHEEL +0 -0
- {literalenum-0.1.1.dist-info → literalenum-0.2.0.dist-info}/entry_points.txt +0 -0
- {literalenum-0.1.1.dist-info → literalenum-0.2.0.dist-info}/licenses/LICENSE +0 -0
literalenum/stubgen.py
CHANGED
|
@@ -384,9 +384,50 @@ def _parse_out_args(raw: list[str] | None) -> list[Path]:
|
|
|
384
384
|
return uniq
|
|
385
385
|
|
|
386
386
|
|
|
387
|
+
def _resolve_root(raw: str) -> str:
|
|
388
|
+
"""Resolve *raw* to a dotted module name importable by Python.
|
|
389
|
+
|
|
390
|
+
Accepts:
|
|
391
|
+
- A dotted import path: ``myapp.models``
|
|
392
|
+
- A file path: ``src/myapp/models.py``
|
|
393
|
+
- A directory path: ``src/myapp/``
|
|
394
|
+
|
|
395
|
+
When a file or directory is given its parent is added to ``sys.path``
|
|
396
|
+
so that ``importlib`` can find it.
|
|
397
|
+
"""
|
|
398
|
+
import sys
|
|
399
|
+
|
|
400
|
+
p = Path(raw)
|
|
401
|
+
|
|
402
|
+
# --- file path: /some/path/module.py ---
|
|
403
|
+
if p.is_file() and p.suffix == ".py":
|
|
404
|
+
parent = str(p.parent.resolve())
|
|
405
|
+
if parent not in sys.path:
|
|
406
|
+
sys.path.insert(0, parent)
|
|
407
|
+
return p.stem if p.name != "__init__.py" else p.parent.name
|
|
408
|
+
|
|
409
|
+
# --- directory path: /some/path/package/ ---
|
|
410
|
+
if p.is_dir():
|
|
411
|
+
parent = str(p.parent.resolve())
|
|
412
|
+
if parent not in sys.path:
|
|
413
|
+
sys.path.insert(0, parent)
|
|
414
|
+
return p.name
|
|
415
|
+
|
|
416
|
+
# --- dotted import name (ensure cwd is on path) ---
|
|
417
|
+
cwd = str(Path.cwd())
|
|
418
|
+
if cwd not in sys.path:
|
|
419
|
+
sys.path.insert(0, cwd)
|
|
420
|
+
return raw
|
|
421
|
+
|
|
422
|
+
|
|
387
423
|
def main() -> int:
|
|
388
424
|
ap = argparse.ArgumentParser()
|
|
389
|
-
ap.add_argument(
|
|
425
|
+
ap.add_argument(
|
|
426
|
+
"root",
|
|
427
|
+
help="Root to scan: a dotted import (myapp), "
|
|
428
|
+
"a .py file (src/myapp/models.py), "
|
|
429
|
+
"or a directory (src/myapp/).",
|
|
430
|
+
)
|
|
390
431
|
ap.add_argument(
|
|
391
432
|
"--out",
|
|
392
433
|
action="append",
|
|
@@ -402,7 +443,8 @@ def main() -> int:
|
|
|
402
443
|
|
|
403
444
|
write_adjacent: bool = not args.no_adjacent
|
|
404
445
|
out_roots: list[Path] = _parse_out_args(args.out) if args.out else []
|
|
405
|
-
|
|
446
|
+
root = _resolve_root(args.root)
|
|
447
|
+
infos = _find_literal_enums(root)
|
|
406
448
|
|
|
407
449
|
by_module: dict[str, list[EnumInfo]] = {}
|
|
408
450
|
for e in infos:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: literalenum
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A Python typing construct that provides namespaced literal constants with advanced typing features.
|
|
5
5
|
Project-URL: Homepage, https://github.com/modularizer/literalenum
|
|
6
6
|
Project-URL: Repository, https://github.com/modularizer/literalenum
|
|
@@ -12,6 +12,8 @@ Keywords: python,typehinting
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
|
|
15
|
+
from sample_str_enum_solutions.a_strenum import HttpMethod
|
|
16
|
+
|
|
15
17
|
# LiteralEnum
|
|
16
18
|
|
|
17
19
|
**LiteralEnum** is an experiment/prototype for a proposed Python typing construct:
|
|
@@ -60,10 +62,36 @@ This repo is currently set up as a package under `src/`.
|
|
|
60
62
|
#source .venv/bin/activate
|
|
61
63
|
pip install literalenum
|
|
62
64
|
```
|
|
63
|
-
|
|
65
|
+
## Realistic Current Usage
|
|
64
66
|
```python
|
|
67
|
+
from typing import Literal
|
|
65
68
|
from literalenum import LiteralEnum
|
|
66
69
|
|
|
70
|
+
HttpMethodT = Literal["GET", "POST", "DELETE"]
|
|
71
|
+
class HttpMethod(LiteralEnum):
|
|
72
|
+
GET = "GET"
|
|
73
|
+
POST = "POST"
|
|
74
|
+
DELETE = "DELETE"
|
|
75
|
+
|
|
76
|
+
def handle(method: HttpMethodT) -> None:
|
|
77
|
+
print(f"{method=}")
|
|
78
|
+
|
|
79
|
+
handle("GET") # this should type-check ✅
|
|
80
|
+
handle(HttpMethod.GET) # this should type-check ✅
|
|
81
|
+
handle("git") # ❌ should be rejected by a type checker
|
|
82
|
+
|
|
83
|
+
assert HttpMethod.GET == "GET"
|
|
84
|
+
assert list(HttpMethod) == ["GET", "POST", "DELETE"]
|
|
85
|
+
assert "GET" in HttpMethod
|
|
86
|
+
print(HttpMethod.keys())
|
|
87
|
+
print(HttpMethod.values())
|
|
88
|
+
print(HttpMethod.mapping)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Optimistic Future Usage
|
|
92
|
+
```python
|
|
93
|
+
from typing import LiteralEnum # NOT valid right now
|
|
94
|
+
|
|
67
95
|
class HttpMethod(LiteralEnum):
|
|
68
96
|
GET = "GET"
|
|
69
97
|
POST = "POST"
|
|
@@ -72,8 +100,8 @@ class HttpMethod(LiteralEnum):
|
|
|
72
100
|
def handle(method: HttpMethod) -> None:
|
|
73
101
|
print(f"{method=}")
|
|
74
102
|
|
|
75
|
-
handle("GET") #
|
|
76
|
-
handle(HttpMethod.GET) #
|
|
103
|
+
handle("GET") # the GOAL is that this should type-check ✅ , in reality: it will not unless typecheckers change
|
|
104
|
+
handle(HttpMethod.GET) # the GOAL is that this should type-check ✅ , in reality: it will not unless typecheckers change
|
|
77
105
|
handle("git") # ❌ should be rejected by a type checker
|
|
78
106
|
|
|
79
107
|
assert HttpMethod.GET == "GET"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
literalenum/__init__.py,sha256=Cle3alhK2TPqkjKZ6yEFB3_2yv-y0EwtdYUnbkRG_-s,477
|
|
2
2
|
literalenum/literal_enum.py,sha256=OfB73GCHeZ5G1cAz3EA99zzZsmQ6jtL3xx3AKK-XP-0,3907
|
|
3
3
|
literalenum/mypy_plugin.py,sha256=JExHoi8NP_QJI0eESRed3TdR3DxEVrj7qA6q-bhj3KU,11020
|
|
4
|
-
literalenum/stubgen.py,sha256=
|
|
4
|
+
literalenum/stubgen.py,sha256=IWT774iThGrbXkYOjVcoCd8Osst9InXpwUJvb3EcG4I,15654
|
|
5
5
|
literalenum/compatibility_extensions/__init__.py,sha256=nIY32idsLpo9VyXtDREWMzLAfYUU7K7Zm3Cl69mWR0k,551
|
|
6
6
|
literalenum/compatibility_extensions/annotated.py,sha256=68TxWaCzMdcuFgnyWfWHUtzUClP5r99BMydSufdgcRA,146
|
|
7
7
|
literalenum/compatibility_extensions/bare_class.py,sha256=LXhT5BfIBJmfA8ZQmHfAVyF4IpM9911oUcj4xtonLFM,75
|
|
@@ -20,8 +20,8 @@ literalenum/compatibility_extensions/str_enum.py,sha256=y-VWFyaEDXmNicgyqzdEpsx-
|
|
|
20
20
|
literalenum/compatibility_extensions/strawberry_enum.py,sha256=mjg3Pyy0w_AggRRB_UtuWQiOguiG66eTN5E_rpwd7cg,526
|
|
21
21
|
typing_literalenum.py,sha256=ZoM0rbr-7Hp72uqohJ6enm-eIhUwAHTGBsb-FsQmXJs,24837
|
|
22
22
|
literalenum/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
literalenum-0.
|
|
24
|
-
literalenum-0.
|
|
25
|
-
literalenum-0.
|
|
26
|
-
literalenum-0.
|
|
27
|
-
literalenum-0.
|
|
23
|
+
literalenum-0.2.0.dist-info/METADATA,sha256=2f2bFRLze4cbkzhiL5xogmz_vJyQU4Rqwd_B-PtqOd4,4879
|
|
24
|
+
literalenum-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
25
|
+
literalenum-0.2.0.dist-info/entry_points.txt,sha256=AK8je10LoLMOXuWLjXSqHV2rsTxPW9HlG7YTJGfwkCY,46
|
|
26
|
+
literalenum-0.2.0.dist-info/licenses/LICENSE,sha256=tQZYOMusRS38hVum5uAxSBrSxoQG9w0h6tkyE3RlPmw,1212
|
|
27
|
+
literalenum-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|