graphite-code 1.2.0__py3-none-any.whl → 1.2.1__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.
- graphite/__init__.py +1 -1
- graphite/agent_hooks.py +121 -20
- graphite/ingest.py +16 -3
- {graphite_code-1.2.0.dist-info → graphite_code-1.2.1.dist-info}/METADATA +2 -2
- {graphite_code-1.2.0.dist-info → graphite_code-1.2.1.dist-info}/RECORD +8 -8
- {graphite_code-1.2.0.dist-info → graphite_code-1.2.1.dist-info}/WHEEL +0 -0
- {graphite_code-1.2.0.dist-info → graphite_code-1.2.1.dist-info}/entry_points.txt +0 -0
- {graphite_code-1.2.0.dist-info → graphite_code-1.2.1.dist-info}/licenses/LICENSE +0 -0
graphite/__init__.py
CHANGED
|
@@ -38,4 +38,4 @@ __all__ = ["__version__"]
|
|
|
38
38
|
#: Coarse and hand-maintained by construction. It is a release label, not
|
|
39
39
|
#: evidence that a given fix is present -- to answer that, survey for the marker
|
|
40
40
|
#: the fix introduced, or compare `graphite --version` fingerprints.
|
|
41
|
-
__version__ = "1.2.
|
|
41
|
+
__version__ = "1.2.1"
|
graphite/agent_hooks.py
CHANGED
|
@@ -21,7 +21,9 @@ from .config import Config
|
|
|
21
21
|
from .freshness import check_graph_freshness
|
|
22
22
|
from .graph_io import load_validated_graph_bundle
|
|
23
23
|
from .health import _edge_language, is_placeholder, persisted_resolution
|
|
24
|
+
from .hook_entry import MARKER as _SETUP_MARKER
|
|
24
25
|
from .incident_ledger import record_incident, repo_ledger_dir
|
|
26
|
+
from .ingest import enclosing_git_root
|
|
25
27
|
|
|
26
28
|
SESSION_CONTRACT = (
|
|
27
29
|
"graphite-first: this repo uses a shared code graph. For cross-file questions "
|
|
@@ -34,22 +36,64 @@ SESSION_CONTRACT = (
|
|
|
34
36
|
_FRESHNESS_BUDGET_SECONDS = 2.0
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def
|
|
39
|
+
def _payload_cwd(payload: dict[str, Any]) -> Path:
|
|
40
|
+
"""The directory the session is in. It follows a `cd` in the shell."""
|
|
38
41
|
cwd = payload.get("cwd")
|
|
39
42
|
if isinstance(cwd, str) and cwd:
|
|
40
43
|
return Path(cwd)
|
|
41
44
|
return Path.cwd()
|
|
42
45
|
|
|
43
46
|
|
|
47
|
+
def _repo_root(cwd: Path) -> Path:
|
|
48
|
+
"""The repository a session in `cwd` belongs to: where its graph is.
|
|
49
|
+
|
|
50
|
+
Taking the session's directory for the root made the graph "missing" one
|
|
51
|
+
`cd` below it, and switched the gate off there (#80). The repository is the
|
|
52
|
+
nearest directory upward that holds `.git`, the one place a build of it can
|
|
53
|
+
run (`ingest.enclosing_git_root`).
|
|
54
|
+
|
|
55
|
+
That directory is used only where graphite is already set up: it has a
|
|
56
|
+
graph, or the `GRAPHITE.md` that `init` commits. Anywhere else `cwd` stands,
|
|
57
|
+
as it did before, so a session that wanders into a subfolder of some other
|
|
58
|
+
checkout does not hand the daemon that whole project to build.
|
|
59
|
+
"""
|
|
60
|
+
top = enclosing_git_root(cwd)
|
|
61
|
+
if top is None or top == cwd:
|
|
62
|
+
return cwd
|
|
63
|
+
if (top / "graph-out" / "graph.json").is_file() or (top / _SETUP_MARKER).is_file():
|
|
64
|
+
return top
|
|
65
|
+
return cwd
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _where_to_run(root: Path, cwd: Path) -> str:
|
|
69
|
+
"""One sentence for a session below the repository root, else nothing.
|
|
70
|
+
|
|
71
|
+
The commands these hooks print are run where the agent is, and the CLI
|
|
72
|
+
looks for the graph in its own working directory. Below the root `query`,
|
|
73
|
+
`context` and `check .` report the graph missing and `build .` is refused,
|
|
74
|
+
so a status or a refusal that names no directory sends the agent to a
|
|
75
|
+
command that fails.
|
|
76
|
+
"""
|
|
77
|
+
if cwd == root:
|
|
78
|
+
return ""
|
|
79
|
+
return f" This session is below the repository root: run graphite from `{root}`."
|
|
80
|
+
|
|
81
|
+
|
|
44
82
|
def _activate(root: Path) -> None:
|
|
45
83
|
"""Register this repo as open, so the daemon supervises it and leaves the
|
|
46
84
|
rest of the machine alone.
|
|
47
85
|
|
|
86
|
+
A directory below a checkout's root is never registered. No build can run
|
|
87
|
+
there (`ingest` refuses it), so the daemon would fail on it at every
|
|
88
|
+
discovery cycle for as long as the marker lived.
|
|
89
|
+
|
|
48
90
|
Guarded separately from the caller's own try/except: activation is
|
|
49
91
|
bookkeeping, and this module is fail-open by contract -- a broken registry
|
|
50
92
|
must never cost the agent its session context or its graph-first reminder.
|
|
51
93
|
"""
|
|
52
94
|
try:
|
|
95
|
+
if enclosing_git_root(root) not in (None, root):
|
|
96
|
+
return
|
|
53
97
|
mark_active(root, "claude")
|
|
54
98
|
except Exception:
|
|
55
99
|
return
|
|
@@ -97,7 +141,8 @@ def _freshness_within_budget(root: Path) -> tuple[str, str | None]:
|
|
|
97
141
|
|
|
98
142
|
def handle_session_start(payload: dict[str, Any]) -> dict[str, Any] | None:
|
|
99
143
|
try:
|
|
100
|
-
|
|
144
|
+
cwd = _payload_cwd(payload)
|
|
145
|
+
root = _repo_root(cwd)
|
|
101
146
|
_activate(root)
|
|
102
147
|
if (root / "graph-out" / "graph.json").is_file():
|
|
103
148
|
state, reason = _freshness_within_budget(root)
|
|
@@ -121,7 +166,7 @@ def handle_session_start(payload: dict[str, Any]) -> dict[str, Any] | None:
|
|
|
121
166
|
return {
|
|
122
167
|
"hookSpecificOutput": {
|
|
123
168
|
"hookEventName": "SessionStart",
|
|
124
|
-
"additionalContext": f"{SESSION_CONTRACT}\n{status}",
|
|
169
|
+
"additionalContext": f"{SESSION_CONTRACT}\n{status}{_where_to_run(root, cwd)}",
|
|
125
170
|
}
|
|
126
171
|
}
|
|
127
172
|
except Exception:
|
|
@@ -435,14 +480,22 @@ def _shell_path(text: str, msys: bool) -> Path:
|
|
|
435
480
|
return Path(text)
|
|
436
481
|
|
|
437
482
|
|
|
438
|
-
def _cd_target(start: Path, arguments: list[str], msys: bool) -> Path | None:
|
|
439
|
-
"""The directory `cd <arguments>` leaves the shell in, or None when unknown.
|
|
483
|
+
def _cd_target(start: Path | None, arguments: list[str], msys: bool) -> Path | None:
|
|
484
|
+
"""The directory `cd <arguments>` leaves the shell in, or None when unknown.
|
|
485
|
+
|
|
486
|
+
`start` is None when the hook does not know where the shell is. From there
|
|
487
|
+
only an absolute path leads somewhere known.
|
|
488
|
+
"""
|
|
440
489
|
if len(arguments) != 1 or os.environ.get("CDPATH"):
|
|
441
490
|
return None # with `CDPATH` set, `cd docs` may land somewhere other than `./docs`
|
|
442
491
|
text = arguments[0]
|
|
443
492
|
if text.startswith("-") or _SHELL_EXPANSION_CHARS.intersection(text):
|
|
444
493
|
return None
|
|
445
|
-
target =
|
|
494
|
+
target = _shell_path(text, msys)
|
|
495
|
+
if start is not None:
|
|
496
|
+
target = start / target # an absolute path replaces `start`
|
|
497
|
+
elif not target.is_absolute():
|
|
498
|
+
return None
|
|
446
499
|
try:
|
|
447
500
|
return target if target.is_dir() else None
|
|
448
501
|
except OSError: # pragma: no cover - a path the platform cannot stat
|
|
@@ -542,7 +595,29 @@ def _search_in(name: str, rest: list[str], base: Path | None, msys: bool) -> _Se
|
|
|
542
595
|
return _Search(positional[0], _located(positional[1:], base, msys), fold_case)
|
|
543
596
|
|
|
544
597
|
|
|
545
|
-
def
|
|
598
|
+
def _unplaced(search: _Search, cwd: Path) -> _Search:
|
|
599
|
+
"""`search` when the hook does not know which directory it runs in.
|
|
600
|
+
|
|
601
|
+
An absolute path says where it is. A relative one that names a file in the
|
|
602
|
+
session's directory is still one file's text, as it is at the root:
|
|
603
|
+
`ls && grep x notes.md`. A directory, a path that is not there, and a
|
|
604
|
+
search that names no path could be anywhere in the repository. The search
|
|
605
|
+
is then one of all of it, and no path is left to earn an exemption.
|
|
606
|
+
"""
|
|
607
|
+
placed: list[str] = []
|
|
608
|
+
for text in search.paths:
|
|
609
|
+
path = Path(text)
|
|
610
|
+
if not path.is_absolute():
|
|
611
|
+
path = cwd / path
|
|
612
|
+
if not path.is_file():
|
|
613
|
+
return search._replace(paths=[])
|
|
614
|
+
placed.append(str(path))
|
|
615
|
+
return search._replace(paths=placed)
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def _bash_searches(
|
|
619
|
+
command: str, root: Path, msys: bool = False, cwd: Path | None = None
|
|
620
|
+
) -> list[_Search]:
|
|
546
621
|
"""Every search `command` runs that is not downstream of a pipe.
|
|
547
622
|
|
|
548
623
|
All of them, not the first: `grep x notes.md ; grep -rn <symbol> src/` is
|
|
@@ -557,12 +632,23 @@ def _bash_searches(command: str, root: Path, msys: bool = False) -> list[_Search
|
|
|
557
632
|
`cd docs && ls && grep ...` is not followed. In every such case, and when
|
|
558
633
|
the directory is not one the hook can find, paths resolve against the
|
|
559
634
|
repository root as they did before `cd` was read at all.
|
|
635
|
+
|
|
636
|
+
`cwd` is the directory the shell starts in when that is below the root
|
|
637
|
+
(#80). The line's first command runs there, and so does a search reached
|
|
638
|
+
through searches alone. Once a `cd` or a command the hook does not model
|
|
639
|
+
has run, the shell may be anywhere. At the root that costs nothing, since
|
|
640
|
+
the root holds every directory it could be in. Below the root the session's
|
|
641
|
+
directory holds only itself: from a `docs/` with no code in it,
|
|
642
|
+
`cd ../src ; grep` would pass as a search of `docs/`. There the search
|
|
643
|
+
keeps only the paths that do not depend on where the shell is (`_unplaced`).
|
|
560
644
|
"""
|
|
561
645
|
searches: list[_Search] = []
|
|
562
|
-
base: Path | None = None
|
|
646
|
+
base: Path | None = cwd # None is the repository root
|
|
647
|
+
placed = True # `base` is where the shell is
|
|
648
|
+
moved = False # a `cd`, or a command the hook does not model, has run
|
|
563
649
|
for head in _bash_command_heads(command):
|
|
564
650
|
if head.before != "&&":
|
|
565
|
-
base = None
|
|
651
|
+
base, placed = (None, False) if moved else (cwd, True)
|
|
566
652
|
argv = head.argv
|
|
567
653
|
while argv and _ENV_ASSIGNMENT_RE.match(argv[0]):
|
|
568
654
|
argv = argv[1:]
|
|
@@ -574,16 +660,22 @@ def _bash_searches(command: str, root: Path, msys: bool = False) -> list[_Search
|
|
|
574
660
|
name = name[:-4]
|
|
575
661
|
rest = argv[1:]
|
|
576
662
|
if name in _CD_COMMANDS:
|
|
577
|
-
|
|
663
|
+
moved = True
|
|
664
|
+
# At the root an unplaced shell is read as being at the root. Below
|
|
665
|
+
# it, only an absolute path leads somewhere known.
|
|
666
|
+
start = base or (root if cwd is None else None)
|
|
667
|
+
base = _cd_target(start, rest, msys) if head.after == "&&" else None
|
|
668
|
+
placed = base is not None
|
|
578
669
|
continue
|
|
579
670
|
if name == "git" and rest and rest[0] == "grep":
|
|
580
671
|
name, rest = "grep", rest[1:]
|
|
581
672
|
if name not in _SEARCH_COMMANDS:
|
|
582
|
-
|
|
673
|
+
# `popd`, `builtin cd ..`, a function: the shell may have moved
|
|
674
|
+
base, placed, moved = None, False, True
|
|
583
675
|
continue
|
|
584
676
|
found = _search_in(name, rest, base, msys)
|
|
585
677
|
if found is not None:
|
|
586
|
-
searches.append(found)
|
|
678
|
+
searches.append(found if placed or cwd is None else _unplaced(found, cwd))
|
|
587
679
|
return searches
|
|
588
680
|
|
|
589
681
|
|
|
@@ -692,7 +784,7 @@ def _denial_for(root: Path, searches: list[_Search]) -> str | None:
|
|
|
692
784
|
return None
|
|
693
785
|
|
|
694
786
|
|
|
695
|
-
def _strict_denial(payload: dict[str, Any], root: Path) -> str | None:
|
|
787
|
+
def _strict_denial(payload: dict[str, Any], root: Path, cwd: Path | None = None) -> str | None:
|
|
696
788
|
try:
|
|
697
789
|
tool_input = payload.get("tool_input")
|
|
698
790
|
if not isinstance(tool_input, dict):
|
|
@@ -702,6 +794,10 @@ def _strict_denial(payload: dict[str, Any], root: Path) -> str | None:
|
|
|
702
794
|
return None
|
|
703
795
|
target = tool_input.get("path")
|
|
704
796
|
paths = [target] if isinstance(target, str) and target else []
|
|
797
|
+
if cwd is not None:
|
|
798
|
+
# Below the root: with no `path` the tool searches the session's
|
|
799
|
+
# directory, and a relative one starts there.
|
|
800
|
+
paths = _located(paths, cwd, False)
|
|
705
801
|
# The Grep tool matches case exactly unless `-i` is set. A value that
|
|
706
802
|
# is not plainly "off" is read as on: unsure folds.
|
|
707
803
|
# The tool is built on ripgrep, so it is read as `rg` with no flags of
|
|
@@ -747,7 +843,7 @@ def _cursor_number(value: Any, cast: type) -> Any:
|
|
|
747
843
|
def handle_stop(payload: dict[str, Any]) -> dict[str, Any] | None:
|
|
748
844
|
"""Turn-end savings summary; silent unless graphite was used this turn."""
|
|
749
845
|
try:
|
|
750
|
-
root =
|
|
846
|
+
root = _repo_root(_payload_cwd(payload))
|
|
751
847
|
# Stop fires once per assistant turn, which makes it the heartbeat that
|
|
752
848
|
# keeps a working session inside the activation TTL. It must run before
|
|
753
849
|
# the session_id guard below, which returns early on most turns.
|
|
@@ -821,9 +917,14 @@ def handle_pre_tool_use(payload: dict[str, Any], mode: str) -> dict[str, Any] |
|
|
|
821
917
|
tool_name = payload.get("tool_name")
|
|
822
918
|
if tool_name not in ("Grep", "Glob", "Bash", "PowerShell"):
|
|
823
919
|
return None
|
|
824
|
-
|
|
920
|
+
cwd = _payload_cwd(payload)
|
|
921
|
+
root = _repo_root(cwd)
|
|
825
922
|
if not (root / "graph-out" / "graph.json").is_file():
|
|
826
923
|
return None
|
|
924
|
+
# Two directories, not one: the graph is at `root`, and a search's
|
|
925
|
+
# relative paths start where the shell is.
|
|
926
|
+
below = None if cwd == root else cwd
|
|
927
|
+
where = _where_to_run(root, cwd)
|
|
827
928
|
denial: str | None = None
|
|
828
929
|
if tool_name in ("Bash", "PowerShell"):
|
|
829
930
|
# The matcher now routes EVERY Bash call here, so anything that is
|
|
@@ -835,13 +936,13 @@ def handle_pre_tool_use(payload: dict[str, Any], mode: str) -> dict[str, Any] |
|
|
|
835
936
|
command = tool_input.get("command") if isinstance(tool_input, dict) else None
|
|
836
937
|
# On Windows the Bash tool is Git Bash, which spells drives `/c/...`.
|
|
837
938
|
msys = tool_name == "Bash" and os.name == "nt"
|
|
838
|
-
searches = _bash_searches(command, root, msys) if isinstance(command, str) else []
|
|
939
|
+
searches = _bash_searches(command, root, msys, below) if isinstance(command, str) else []
|
|
839
940
|
if not searches:
|
|
840
941
|
return None
|
|
841
942
|
if mode == "strict":
|
|
842
943
|
denial = _denial_for(root, searches)
|
|
843
944
|
elif mode == "strict" and tool_name == "Grep":
|
|
844
|
-
denial = _strict_denial(payload, root)
|
|
945
|
+
denial = _strict_denial(payload, root, below)
|
|
845
946
|
if denial is not None:
|
|
846
947
|
health = persisted_resolution(
|
|
847
948
|
root,
|
|
@@ -858,19 +959,19 @@ def handle_pre_tool_use(payload: dict[str, Any], mode: str) -> dict[str, Any] |
|
|
|
858
959
|
"hookSpecificOutput": {
|
|
859
960
|
"hookEventName": "PreToolUse",
|
|
860
961
|
"permissionDecision": "deny",
|
|
861
|
-
"permissionDecisionReason": denial,
|
|
962
|
+
"permissionDecisionReason": denial + where,
|
|
862
963
|
}
|
|
863
964
|
}
|
|
864
965
|
return {
|
|
865
966
|
"hookSpecificOutput": {
|
|
866
967
|
"hookEventName": "PreToolUse",
|
|
867
|
-
"additionalContext": PRE_TOOL_REMINDER + STRICT_SUSPENSION_NOTE,
|
|
968
|
+
"additionalContext": PRE_TOOL_REMINDER + STRICT_SUSPENSION_NOTE + where,
|
|
868
969
|
}
|
|
869
970
|
}
|
|
870
971
|
return {
|
|
871
972
|
"hookSpecificOutput": {
|
|
872
973
|
"hookEventName": "PreToolUse",
|
|
873
|
-
"additionalContext": PRE_TOOL_REMINDER,
|
|
974
|
+
"additionalContext": PRE_TOOL_REMINDER + where,
|
|
874
975
|
}
|
|
875
976
|
}
|
|
876
977
|
except Exception:
|
graphite/ingest.py
CHANGED
|
@@ -157,6 +157,19 @@ def _normalize_git_path(root: Path, value: str) -> str | None:
|
|
|
157
157
|
return native_path.as_posix()
|
|
158
158
|
|
|
159
159
|
|
|
160
|
+
def enclosing_git_root(path: Path) -> Path | None:
|
|
161
|
+
"""The nearest directory, from `path` upward, that holds `.git`.
|
|
162
|
+
|
|
163
|
+
`.git` is a directory in a clone and a file in a linked worktree or a
|
|
164
|
+
submodule, so it is tested for existence only. None means `path` is in no
|
|
165
|
+
repository at all.
|
|
166
|
+
"""
|
|
167
|
+
for directory in (path, *path.parents):
|
|
168
|
+
if os.path.lexists(directory / ".git"):
|
|
169
|
+
return directory
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
|
|
160
173
|
def _git_ls_files(
|
|
161
174
|
root: Path,
|
|
162
175
|
*,
|
|
@@ -164,9 +177,9 @@ def _git_ls_files(
|
|
|
164
177
|
is_eligible: Callable[[str], bool] | None = None,
|
|
165
178
|
) -> list[str] | None:
|
|
166
179
|
"""Return bounded Git files, or None only when *root* is not a Git repository."""
|
|
167
|
-
|
|
168
|
-
if
|
|
169
|
-
if
|
|
180
|
+
enclosing = enclosing_git_root(root)
|
|
181
|
+
if enclosing != root:
|
|
182
|
+
if enclosing is not None:
|
|
170
183
|
raise IngestError("nested Git roots are unsupported")
|
|
171
184
|
return None
|
|
172
185
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: graphite-code
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Local-first, zero-LLM knowledge graph extraction for codebases.
|
|
5
5
|
Project-URL: Homepage, https://github.com/jared0565/graphite
|
|
6
6
|
Project-URL: Repository, https://github.com/jared0565/graphite
|
|
@@ -48,7 +48,7 @@ Description-Content-Type: text/markdown
|
|
|
48
48
|
|
|
49
49
|
Local-first, deterministic knowledge graph extraction for codebases — zero-LLM, daemon-maintained, agent-agnostic.
|
|
50
50
|
|
|
51
|
-
**Status: 1.2.
|
|
51
|
+
**Status: 1.2.1, production/stable.** Published on PyPI as
|
|
52
52
|
[`graphite-code`](https://pypi.org/project/graphite-code/) with PEP 740
|
|
53
53
|
attestations; supported on Windows, Linux and macOS with Python 3.11–3.14
|
|
54
54
|
(every cell gates CI). What 1.x promises — CLI, JSON outputs, `graph.json`,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
graphite/__init__.py,sha256=
|
|
1
|
+
graphite/__init__.py,sha256=qZMmOAr0ZddEL5nGkmdWPpCtYeSJuYsNahTqQSuDWo8,2181
|
|
2
2
|
graphite/__main__.py,sha256=Bp5bcXE6M0AnuNW1LjOXOEvGG5r0fXZoeRb_k5Yxphs,149
|
|
3
3
|
graphite/_cleanup_worker.py,sha256=oIXOPa1jHVP8ePRSwn27nZEHOAc4DSBrjeH2Ds9wuq8,19619
|
|
4
4
|
graphite/_win32_ctypes.py,sha256=YLH4kpKjL7zUUOs9E8C-Kjdy45PJBd6eRUeKwiKdSV4,1476
|
|
5
5
|
graphite/activation.py,sha256=Jcgk8AFvqbMNQiPAa2MTzSO0BAYRC5FX6MsZUjbDe1I,5249
|
|
6
|
-
graphite/agent_hooks.py,sha256=
|
|
6
|
+
graphite/agent_hooks.py,sha256=m9nkRRkfqgfioYFxwG4TDEF2JhAL_U6zXWXLkl3OasE,42073
|
|
7
7
|
graphite/agent_settings.py,sha256=Ec95ilPhkPOM3vW67pdsjYivnCyc5uCqWfCBu-DLI3A,11085
|
|
8
8
|
graphite/analyze.py,sha256=BwiZ4lkQ8Oo8WvnIGLI03YSNUpynYvV46tVbzHH5iWQ,9304
|
|
9
9
|
graphite/answer_contract.py,sha256=ON2i3QRc1OpyM6_k3Y6wCw-CvdD2LyYqfayA6h_nxrI,27509
|
|
@@ -33,7 +33,7 @@ graphite/hook_entry.py,sha256=0lfCZB9-B_9QBKagLhV_VIMVFcrOeAwpLcFXUjhMMpg,2655
|
|
|
33
33
|
graphite/hookinstall.py,sha256=1fCjMeQsKVfOmrJm42p94SKL14hZ31R-WANZPZzkzmM,9344
|
|
34
34
|
graphite/hookshim.py,sha256=4to9xkNOWPjbk1Es97KTTknjJM9gdHkbEDjCQq8ntec,3771
|
|
35
35
|
graphite/incident_ledger.py,sha256=wHW-P_PJNollM_L9bAXHaxFeLb89wMXs7XX0VrH7aSw,8654
|
|
36
|
-
graphite/ingest.py,sha256=
|
|
36
|
+
graphite/ingest.py,sha256=hQoRDcaIZkaCg9GA6JKuJsq-Ntnup1-f0jrPhRFX1fs,9176
|
|
37
37
|
graphite/init.py,sha256=TD7996Wp51-anUi1KjTyWyeMlXyR14BWnMDzK3uSZ0Y,41241
|
|
38
38
|
graphite/io.py,sha256=YBXfMcPsv1Lzun8ByW4BQlfgMm54akckLFrUhwWtleI,2996
|
|
39
39
|
graphite/launchd_agent.py,sha256=rmKhhCbB-9FDU_3A1b2OlZxKpxZqdgtYnLbzkFMs_rI,4529
|
|
@@ -112,8 +112,8 @@ graphite/routing/zai_edit.py,sha256=Kra2tI9GkntQAhV1vNHlFlp4sY-ksq2-bY4N9fEfLEc,
|
|
|
112
112
|
graphite/routing/zai_executor.py,sha256=cHUl7DbWRUhYg9Lwm3OiP6H3dI70y_b8iAWCyfgOPi0,6636
|
|
113
113
|
graphite/routing/zai_probe.py,sha256=HL2vM8s2J4-n8Bp3l7QLpWLEk-PhZrt_rLc2cY65hvU,4771
|
|
114
114
|
graphite/ts_resolver.mjs,sha256=wiKDWkJIC9__3wL49ty4W8hRc5biisNNtFhH1aFA47A,10822
|
|
115
|
-
graphite_code-1.2.
|
|
116
|
-
graphite_code-1.2.
|
|
117
|
-
graphite_code-1.2.
|
|
118
|
-
graphite_code-1.2.
|
|
119
|
-
graphite_code-1.2.
|
|
115
|
+
graphite_code-1.2.1.dist-info/METADATA,sha256=hPtv7G5SJsHx021OGAhswsIgr1v93-VEOVdw_ynaYY8,48402
|
|
116
|
+
graphite_code-1.2.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
117
|
+
graphite_code-1.2.1.dist-info/entry_points.txt,sha256=-BpYAYFyn58DYi-hrFW9hMz6mTwNsYI44s9gaef4MiM,87
|
|
118
|
+
graphite_code-1.2.1.dist-info/licenses/LICENSE,sha256=mfotJ1Lk0VVUgoEPOIR7-x5cvYiz2UkuVH7e3fhoDiY,1066
|
|
119
|
+
graphite_code-1.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|