substratum-cli 0.1.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.
Files changed (42) hide show
  1. substratum_cli/README.md +51 -0
  2. substratum_cli/__init__.py +6 -0
  3. substratum_cli/__main__.py +7 -0
  4. substratum_cli/_vendor/__init__.py +0 -0
  5. substratum_cli/_vendor/_pro_test_derive.py +169 -0
  6. substratum_cli/account.py +62 -0
  7. substratum_cli/cli.py +185 -0
  8. substratum_cli/codes.py +114 -0
  9. substratum_cli/commands/__init__.py +0 -0
  10. substratum_cli/commands/apply.py +49 -0
  11. substratum_cli/commands/auth.py +37 -0
  12. substratum_cli/commands/commit.py +40 -0
  13. substratum_cli/commands/explain.py +63 -0
  14. substratum_cli/commands/failing.py +80 -0
  15. substratum_cli/commands/fix.py +48 -0
  16. substratum_cli/commands/history.py +15 -0
  17. substratum_cli/commands/init_cmd.py +155 -0
  18. substratum_cli/commands/replay.py +68 -0
  19. substratum_cli/commands/scaffold.py +71 -0
  20. substratum_cli/commands/show.py +18 -0
  21. substratum_cli/commands/undo.py +28 -0
  22. substratum_cli/commands/verify.py +193 -0
  23. substratum_cli/commands/write.py +42 -0
  24. substratum_cli/config.py +49 -0
  25. substratum_cli/diffs.py +106 -0
  26. substratum_cli/engine.py +154 -0
  27. substratum_cli/gitio.py +102 -0
  28. substratum_cli/langscan.py +110 -0
  29. substratum_cli/product_ops.py +639 -0
  30. substratum_cli/refusals.py +127 -0
  31. substratum_cli/remote.py +140 -0
  32. substratum_cli/render.py +332 -0
  33. substratum_cli/result.py +185 -0
  34. substratum_cli/run_store.py +162 -0
  35. substratum_cli/runid.py +69 -0
  36. substratum_cli/session.py +558 -0
  37. substratum_cli/style.py +128 -0
  38. substratum_cli-0.1.0.dist-info/METADATA +69 -0
  39. substratum_cli-0.1.0.dist-info/RECORD +42 -0
  40. substratum_cli-0.1.0.dist-info/WHEEL +5 -0
  41. substratum_cli-0.1.0.dist-info/entry_points.txt +2 -0
  42. substratum_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,110 @@
1
+ """Multi-language declaration scanner -- every language Substratum services, no gaps, no deps.
2
+
3
+ Grain: name the top-level definitions (functions / methods / classes / structs / interfaces / types
4
+ / enums) per file, so the `summarize` surface describes a codebase in ANY serviced language, not just
5
+ Python. Stdlib-only (air-gapped): Python is exact via `ast`; Go and TS/JS use closed-class declaration
6
+ regexes. NOT a full parser -- summarize needs symbol NAMES + kind, which regex resolves faithfully at
7
+ this grain. Returns a flat list of {name, kind} declarations; the caller aggregates + glosses.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import ast
12
+ import re
13
+ from typing import Dict, List
14
+
15
+ # every extension we service -> language bucket
16
+ LANGS: Dict[str, str] = {
17
+ ".py": "py", ".pyi": "py",
18
+ ".go": "go",
19
+ ".ts": "ts", ".tsx": "ts", ".mts": "ts", ".cts": "ts",
20
+ ".js": "js", ".jsx": "js", ".mjs": "js", ".cjs": "js",
21
+ }
22
+
23
+ _IDENT = r"[A-Za-z_$][\w$]*"
24
+
25
+
26
+ def scan(text: str, ext: str) -> List[dict]:
27
+ """[{name, kind}] for one file. kind in {function, method, class, struct, interface, type, enum}."""
28
+ lang = LANGS.get(ext)
29
+ if lang == "py":
30
+ return _scan_py(text)
31
+ if lang == "go":
32
+ return _scan_go(text)
33
+ if lang in ("ts", "js"):
34
+ return _scan_ts(text)
35
+ return []
36
+
37
+
38
+ def _scan_py(text: str) -> List[dict]:
39
+ out: List[dict] = []
40
+ try:
41
+ tree = ast.parse(text)
42
+ except Exception:
43
+ return out
44
+ for node in tree.body:
45
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
46
+ out.append({"name": node.name, "kind": "function"})
47
+ elif isinstance(node, ast.ClassDef):
48
+ out.append({"name": node.name, "kind": "class"})
49
+ for m in node.body:
50
+ if isinstance(m, (ast.FunctionDef, ast.AsyncFunctionDef)):
51
+ out.append({"name": m.name, "kind": "method"})
52
+ return out
53
+
54
+
55
+ _GO_FUNC = re.compile(r"^func\s+(" + _IDENT + r")\s*\(", re.M)
56
+ _GO_METHOD = re.compile(r"^func\s+\([^)]*\)\s+(" + _IDENT + r")\s*\(", re.M)
57
+ _GO_TYPE = re.compile(r"^type\s+(" + _IDENT + r")\s+(struct|interface)\b", re.M)
58
+ _GO_TYPE_OTHER = re.compile(r"^type\s+(" + _IDENT + r")\s+(?!struct|interface)\S", re.M)
59
+
60
+
61
+ def _scan_go(text: str) -> List[dict]:
62
+ out: List[dict] = []
63
+ for m in _GO_FUNC.finditer(text):
64
+ out.append({"name": m.group(1), "kind": "function"})
65
+ for m in _GO_METHOD.finditer(text):
66
+ out.append({"name": m.group(1), "kind": "method"})
67
+ for m in _GO_TYPE.finditer(text):
68
+ out.append({"name": m.group(1), "kind": "struct" if m.group(2) == "struct" else "interface"})
69
+ for m in _GO_TYPE_OTHER.finditer(text):
70
+ out.append({"name": m.group(1), "kind": "type"})
71
+ return out
72
+
73
+
74
+ _TS_FUNC = re.compile(
75
+ r"^\s*(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s*(" + _IDENT + r")", re.M)
76
+ _TS_ARROW = re.compile(
77
+ r"^\s*(?:export\s+)?(?:default\s+)?(?:const|let|var)\s+(" + _IDENT +
78
+ r")\s*(?::[^=]+)?=\s*(?:async\s*)?(?:<[^>]*>\s*)?\([^)]*\)\s*(?::[^=]+?)?=>", re.M)
79
+ _TS_CLASS = re.compile(r"^\s*(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+(" + _IDENT + r")", re.M)
80
+ _TS_IFACE = re.compile(r"^\s*(?:export\s+)?interface\s+(" + _IDENT + r")", re.M)
81
+ _TS_TYPE = re.compile(r"^\s*(?:export\s+)?type\s+(" + _IDENT + r")\s*[=<]", re.M)
82
+ _TS_ENUM = re.compile(r"^\s*(?:export\s+)?(?:const\s+)?enum\s+(" + _IDENT + r")", re.M)
83
+ # a class-body member method: indented `name(args) {` or `name(args):` (not a control keyword)
84
+ _TS_METHOD = re.compile(
85
+ r"^\s+(?:public\s+|private\s+|protected\s+|static\s+|async\s+|readonly\s+|get\s+|set\s+|\*\s*)*"
86
+ r"(" + _IDENT + r")\s*\([^)]*\)\s*[:{]", re.M)
87
+ _TS_KEYWORDS = frozenset({"if", "for", "while", "switch", "catch", "return", "function",
88
+ "constructor", "super", "await", "yield", "typeof", "case", "do", "else"})
89
+
90
+
91
+ def _scan_ts(text: str) -> List[dict]:
92
+ out: List[dict] = []
93
+ top_fn = set()
94
+ for m in _TS_FUNC.finditer(text):
95
+ out.append({"name": m.group(1), "kind": "function"}); top_fn.add(m.group(1))
96
+ for m in _TS_ARROW.finditer(text):
97
+ out.append({"name": m.group(1), "kind": "function"}); top_fn.add(m.group(1))
98
+ for m in _TS_CLASS.finditer(text):
99
+ out.append({"name": m.group(1), "kind": "class"})
100
+ for m in _TS_IFACE.finditer(text):
101
+ out.append({"name": m.group(1), "kind": "interface"})
102
+ for m in _TS_TYPE.finditer(text):
103
+ out.append({"name": m.group(1), "kind": "type"})
104
+ for m in _TS_ENUM.finditer(text):
105
+ out.append({"name": m.group(1), "kind": "enum"})
106
+ for m in _TS_METHOD.finditer(text): # best-effort class methods (indented members)
107
+ nm = m.group(1)
108
+ if nm not in _TS_KEYWORDS and nm not in top_fn:
109
+ out.append({"name": nm, "kind": "method"})
110
+ return out