gitgrip 1.5.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.
- gitgrip-1.5.0.dist-info/METADATA +13 -0
- gitgrip-1.5.0.dist-info/RECORD +80 -0
- gitgrip-1.5.0.dist-info/WHEEL +5 -0
- gitgrip-1.5.0.dist-info/entry_points.txt +2 -0
- gitgrip-1.5.0.dist-info/top_level.txt +2 -0
- gr2/__init__.py +0 -0
- gr2/overlay/__init__.py +6 -0
- gr2/overlay/activate.py +196 -0
- gr2/overlay/agent_manifest.py +138 -0
- gr2/overlay/cli.py +181 -0
- gr2/overlay/cross_repo.py +124 -0
- gr2/overlay/drivers.py +113 -0
- gr2/overlay/introspection.py +155 -0
- gr2/overlay/language_drivers.py +115 -0
- gr2/overlay/objects.py +412 -0
- gr2/overlay/perf.py +251 -0
- gr2/overlay/refs.py +36 -0
- gr2/overlay/trust.py +150 -0
- gr2/overlay/types.py +69 -0
- gr2/overlay/units.py +313 -0
- gr2/overlay/workspace_spec.py +59 -0
- gr2/prototypes/__init__.py +0 -0
- gr2/prototypes/cache_materialization_probe.py +190 -0
- gr2/prototypes/concurrent_event_stress.py +199 -0
- gr2/prototypes/concurrent_lease_stress.py +240 -0
- gr2/prototypes/concurrent_workspace_cap_stress.py +231 -0
- gr2/prototypes/contribution_protocol.py +665 -0
- gr2/prototypes/cross_mode_lane_stress.py +986 -0
- gr2/prototypes/jsonl_store.py +158 -0
- gr2/prototypes/lane_workspace_prototype.py +2088 -0
- gr2/prototypes/layout_model_probe.py +139 -0
- gr2/prototypes/propagation_daemon.py +546 -0
- gr2/prototypes/propagation_state_machine.py +1478 -0
- gr2/prototypes/python_exec_playground.py +194 -0
- gr2/prototypes/python_hook_runtime_playground.py +240 -0
- gr2/prototypes/python_migration_playground.py +144 -0
- gr2/prototypes/python_review_checkout_playground.py +242 -0
- gr2/prototypes/python_spec_apply_playground.py +282 -0
- gr2/prototypes/real_git_lane_materialization.py +248 -0
- gr2/prototypes/real_git_playground.py +334 -0
- gr2/prototypes/recall_lane_history.py +274 -0
- gr2/prototypes/repo_maintenance_prototype.py +659 -0
- gr2/prototypes/repo_transport_probe.py +147 -0
- gr2/python_cli/__init__.py +2 -0
- gr2/python_cli/__main__.py +6 -0
- gr2/python_cli/add.py +51 -0
- gr2/python_cli/app.py +2516 -0
- gr2/python_cli/branch.py +67 -0
- gr2/python_cli/channel_bridge.py +131 -0
- gr2/python_cli/clone_exec.py +1019 -0
- gr2/python_cli/commit.py +199 -0
- gr2/python_cli/config.py +291 -0
- gr2/python_cli/env_exec.py +419 -0
- gr2/python_cli/events.py +529 -0
- gr2/python_cli/execops.py +372 -0
- gr2/python_cli/failures.py +98 -0
- gr2/python_cli/file_exec.py +256 -0
- gr2/python_cli/gitops.py +226 -0
- gr2/python_cli/grip.py +1337 -0
- gr2/python_cli/grip_cli.py +493 -0
- gr2/python_cli/hooks.py +450 -0
- gr2/python_cli/launch_exec.py +786 -0
- gr2/python_cli/merge_verification.py +274 -0
- gr2/python_cli/migration.py +985 -0
- gr2/python_cli/open_gr_review.py +699 -0
- gr2/python_cli/platform.py +441 -0
- gr2/python_cli/pr.py +487 -0
- gr2/python_cli/project_review.py +314 -0
- gr2/python_cli/prune.py +365 -0
- gr2/python_cli/push.py +172 -0
- gr2/python_cli/review.py +462 -0
- gr2/python_cli/review_ephemeral.py +143 -0
- gr2/python_cli/review_run.py +621 -0
- gr2/python_cli/spec_apply.py +1285 -0
- gr2/python_cli/staging_cleanup.py +205 -0
- gr2/python_cli/syncops.py +920 -0
- gr2/python_cli/target.py +100 -0
- gr2/python_cli/workspace_snapshot.py +105 -0
- gr2/schemas/gr2-materialization-plan-v1.schema.json +191 -0
- gr2_overlay/__init__.py +37 -0
gr2/python_cli/target.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""gr2 `target`: the stored PR target (`[settings].target` in the workspace spec).
|
|
2
|
+
|
|
3
|
+
This is the WRITER for the value gr2 `prune` already reads. gr1's `gr target set`
|
|
4
|
+
writes the gr1 manifest (`.gitgrip/...`), a different file; this writes
|
|
5
|
+
`.grip/workspace_spec.toml`, which is what gr2 reads.
|
|
6
|
+
|
|
7
|
+
The write is a faithful round-trip -- `tomllib.load` the whole spec, set (or
|
|
8
|
+
remove) `settings.target`, `tomli_w.dumps` the whole thing back, atomically --
|
|
9
|
+
so every other field (repos, units, workspace_name, an existing merge_method)
|
|
10
|
+
survives untouched. It deliberately does NOT go through `_write_workspace_spec`,
|
|
11
|
+
which regenerates the spec from repos/units alone and emits no `[settings]` table
|
|
12
|
+
at all (it would silently drop merge_method). The spec is machine-written, so the
|
|
13
|
+
round-trip dropping TOML comments is a non-issue -- there are none to keep.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import tempfile
|
|
20
|
+
import tomllib
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
import tomli_w
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TargetError(Exception):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_SPEC_REL = (".grip", "workspace_spec.toml")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def spec_path(workspace_root: Path) -> Path:
|
|
34
|
+
return workspace_root.joinpath(*_SPEC_REL)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _load(workspace_root: Path) -> dict:
|
|
38
|
+
path = spec_path(workspace_root)
|
|
39
|
+
if not path.is_file():
|
|
40
|
+
raise TargetError(
|
|
41
|
+
f"no workspace spec at {path}: a stored target needs a workspace "
|
|
42
|
+
f"(run inside a gripspace, or set --target on prune directly)"
|
|
43
|
+
)
|
|
44
|
+
with path.open("rb") as fh:
|
|
45
|
+
return tomllib.load(fh)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _settings(spec: dict) -> dict:
|
|
49
|
+
settings = spec.get("settings", {})
|
|
50
|
+
if not isinstance(settings, dict):
|
|
51
|
+
raise TargetError("workspace spec [settings] must be a table")
|
|
52
|
+
return settings
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _atomic_write(workspace_root: Path, spec: dict) -> None:
|
|
56
|
+
path = spec_path(workspace_root)
|
|
57
|
+
data = tomli_w.dumps(spec)
|
|
58
|
+
# Atomic: write a sibling temp file then os.replace, so a crash mid-write
|
|
59
|
+
# can never leave a truncated spec.
|
|
60
|
+
fd, tmp = tempfile.mkstemp(dir=str(path.parent), prefix=".workspace_spec.", suffix=".toml")
|
|
61
|
+
try:
|
|
62
|
+
with os.fdopen(fd, "w") as fh:
|
|
63
|
+
fh.write(data)
|
|
64
|
+
os.replace(tmp, path)
|
|
65
|
+
finally:
|
|
66
|
+
if os.path.exists(tmp):
|
|
67
|
+
os.unlink(tmp)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def show_target(workspace_root: Path) -> str | None:
|
|
71
|
+
"""The stored `[settings].target`, or None if unset."""
|
|
72
|
+
value = _settings(_load(workspace_root)).get("target")
|
|
73
|
+
if value is None:
|
|
74
|
+
return None
|
|
75
|
+
if not isinstance(value, str):
|
|
76
|
+
raise TargetError("workspace setting target must be a string")
|
|
77
|
+
return value
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def set_target(workspace_root: Path, branch: str) -> None:
|
|
81
|
+
"""Write `[settings].target = <branch>`, preserving every other field."""
|
|
82
|
+
if not branch:
|
|
83
|
+
raise TargetError("target branch must be a non-empty name")
|
|
84
|
+
spec = _load(workspace_root)
|
|
85
|
+
spec.setdefault("settings", {})
|
|
86
|
+
if not isinstance(spec["settings"], dict):
|
|
87
|
+
raise TargetError("workspace spec [settings] must be a table")
|
|
88
|
+
spec["settings"]["target"] = branch
|
|
89
|
+
_atomic_write(workspace_root, spec)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def unset_target(workspace_root: Path) -> bool:
|
|
93
|
+
"""Remove `[settings].target` if present. Returns True if something was removed."""
|
|
94
|
+
spec = _load(workspace_root)
|
|
95
|
+
settings = spec.get("settings")
|
|
96
|
+
if isinstance(settings, dict) and "target" in settings:
|
|
97
|
+
del settings["target"]
|
|
98
|
+
_atomic_write(workspace_root, spec)
|
|
99
|
+
return True
|
|
100
|
+
return False
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Capture a materialized lane's resolved repository state as one kind=workspace
|
|
2
|
+
gr commit (R2 Milestone 1, the section-5 semantic tree for the workspace kind).
|
|
3
|
+
|
|
4
|
+
The workspace gr commit is a reproduction coordinate: it records, per repo, the
|
|
5
|
+
exact head a checkout must materialize plus the base it builds on. A repo with
|
|
6
|
+
uncommitted changes is REFUSED, not recorded — snapshotting a dirty tree would
|
|
7
|
+
record a coordinate that does not reproduce the author's actual state. Commit
|
|
8
|
+
the lane first (``gr2 commit`` lane-aware), then snapshot.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from gr2.prototypes import lane_workspace_prototype as lane_proto
|
|
16
|
+
|
|
17
|
+
from . import grip
|
|
18
|
+
from .gitops import git, repo_dirty
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class WorkspaceSnapshotError(Exception):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _resolve_head(repo_root: Path, key: str, fork_base_sha: str | None) -> tuple[str, str]:
|
|
26
|
+
"""(commit, base) for one lane repo.
|
|
27
|
+
|
|
28
|
+
`commit` is HEAD. `base` is the RECORDED fork base, never derived
|
|
29
|
+
from HEAD^: a lane with N commits must record where its work began, and HEAD^
|
|
30
|
+
is only the (N-1)th commit. A lane with no recorded fork base reads base as
|
|
31
|
+
unknown and is REFUSED here — the reproduction path never substitutes HEAD^ or
|
|
32
|
+
a live merge-base for a coordinate it does not actually know.
|
|
33
|
+
"""
|
|
34
|
+
head = git(repo_root, "rev-parse", "--verify", "HEAD")
|
|
35
|
+
if head.returncode != 0 or not head.stdout.strip():
|
|
36
|
+
raise WorkspaceSnapshotError(f"repo {key} has no HEAD to snapshot")
|
|
37
|
+
commit = head.stdout.strip()
|
|
38
|
+
if not fork_base_sha:
|
|
39
|
+
raise WorkspaceSnapshotError(
|
|
40
|
+
f"repo {key} has no recorded fork base; base is unknown. Recreate the lane "
|
|
41
|
+
"with a recorded fork base; the snapshot will not substitute HEAD^."
|
|
42
|
+
)
|
|
43
|
+
# The recorded fork base must be a real commit in this repo and an ancestor of
|
|
44
|
+
# HEAD — otherwise it is not a coordinate HEAD actually builds on.
|
|
45
|
+
if git(repo_root, "rev-parse", "--verify", "--quiet", f"{fork_base_sha}^{{commit}}").returncode != 0:
|
|
46
|
+
raise WorkspaceSnapshotError(
|
|
47
|
+
f"repo {key} recorded fork base {fork_base_sha} is not a commit in this repo"
|
|
48
|
+
)
|
|
49
|
+
if git(repo_root, "merge-base", "--is-ancestor", fork_base_sha, commit).returncode != 0:
|
|
50
|
+
raise WorkspaceSnapshotError(
|
|
51
|
+
f"repo {key} recorded fork base {fork_base_sha} is not an ancestor of HEAD {commit}"
|
|
52
|
+
)
|
|
53
|
+
return commit, fork_base_sha
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def resolve_lane_repos(workspace_root: Path, owner_unit: str, lane_name: str) -> list[dict[str, str]]:
|
|
57
|
+
"""Resolve every repo of a materialized lane into the section-5 fields.
|
|
58
|
+
|
|
59
|
+
Refuses a repo with uncommitted changes (a snapshot must reproduce).
|
|
60
|
+
"""
|
|
61
|
+
workspace_root = Path(workspace_root).resolve()
|
|
62
|
+
doc = lane_proto.load_lane_doc(workspace_root, owner_unit, lane_name)
|
|
63
|
+
fork_base = doc.get("fork_base", {})
|
|
64
|
+
spec = lane_proto.load_workspace_spec(workspace_root)
|
|
65
|
+
spec_by_name = {r.get("name"): r for r in spec.get("repos", [])}
|
|
66
|
+
lane_root = lane_proto.lane_dir(workspace_root, owner_unit, lane_name)
|
|
67
|
+
|
|
68
|
+
resolved: list[dict[str, str]] = []
|
|
69
|
+
for key in doc.get("repos", []):
|
|
70
|
+
repo_root = lane_root / "repos" / key
|
|
71
|
+
if not (repo_root / ".git").exists():
|
|
72
|
+
raise WorkspaceSnapshotError(f"repo {key} is not materialized at {repo_root}")
|
|
73
|
+
if repo_dirty(repo_root):
|
|
74
|
+
raise WorkspaceSnapshotError(
|
|
75
|
+
f"repo {key} has uncommitted changes; commit the lane before snapshotting"
|
|
76
|
+
)
|
|
77
|
+
repo_spec = spec_by_name.get(key)
|
|
78
|
+
if not repo_spec:
|
|
79
|
+
raise WorkspaceSnapshotError(f"repo {key} is not in the workspace spec")
|
|
80
|
+
commit, base = _resolve_head(repo_root, key, fork_base.get(key, {}).get("sha"))
|
|
81
|
+
resolved.append({
|
|
82
|
+
"key": key,
|
|
83
|
+
"remote": str(repo_spec.get("url", "")),
|
|
84
|
+
"path": str(repo_spec.get("path", "")),
|
|
85
|
+
"commit": commit,
|
|
86
|
+
"base": base,
|
|
87
|
+
})
|
|
88
|
+
return resolved
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def snapshot_lane(workspace_root: Path, owner_unit: str, lane_name: str) -> str:
|
|
92
|
+
"""Resolve a materialized lane and write one kind=workspace gr commit.
|
|
93
|
+
|
|
94
|
+
Returns the gr commit id (the reproduction coordinate).
|
|
95
|
+
"""
|
|
96
|
+
workspace_root = Path(workspace_root).resolve()
|
|
97
|
+
repos = resolve_lane_repos(workspace_root, owner_unit, lane_name)
|
|
98
|
+
if not repos:
|
|
99
|
+
raise WorkspaceSnapshotError(f"lane {owner_unit}/{lane_name} has no repos to snapshot")
|
|
100
|
+
return grip.create_workspace_commit(workspace_root, repos)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def read_snapshot(workspace_root: Path, commit: str) -> list[dict[str, str]]:
|
|
104
|
+
"""Decode a kind=workspace gr commit's resolved repository fields."""
|
|
105
|
+
return grip.read_workspace_commit(Path(workspace_root).resolve(), commit)
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:synapt:gr2:materialization-plan:v1",
|
|
4
|
+
"title": "gr2 MaterializationPlan v1",
|
|
5
|
+
"description": "Identity-free, one-opaque-unit materialization plan consumed by the neutral gr2 executor.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schema_version",
|
|
10
|
+
"plan_id",
|
|
11
|
+
"unit_key",
|
|
12
|
+
"workspace_spec_sha256",
|
|
13
|
+
"operations"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"schema_version": {
|
|
17
|
+
"const": 1
|
|
18
|
+
},
|
|
19
|
+
"plan_id": {
|
|
20
|
+
"$ref": "#/$defs/opaqueToken"
|
|
21
|
+
},
|
|
22
|
+
"unit_key": {
|
|
23
|
+
"$ref": "#/$defs/opaqueToken"
|
|
24
|
+
},
|
|
25
|
+
"workspace_spec_sha256": {
|
|
26
|
+
"$ref": "#/$defs/sha256"
|
|
27
|
+
},
|
|
28
|
+
"operations": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"minItems": 1,
|
|
31
|
+
"items": {
|
|
32
|
+
"oneOf": [
|
|
33
|
+
{
|
|
34
|
+
"$ref": "#/$defs/cloneOperation"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"$ref": "#/$defs/venvOperation"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"$ref": "#/$defs/editableInstallOperation"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"$ref": "#/$defs/projectFileOperation"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"$defs": {
|
|
50
|
+
"opaqueToken": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1,
|
|
53
|
+
"maxLength": 128,
|
|
54
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
|
|
55
|
+
},
|
|
56
|
+
"sha256": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
59
|
+
},
|
|
60
|
+
"nonEmptyString": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1,
|
|
63
|
+
"maxLength": 2048,
|
|
64
|
+
"pattern": "^[^\\u0000]+$"
|
|
65
|
+
},
|
|
66
|
+
"workspaceRelativePath": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"minLength": 1,
|
|
69
|
+
"maxLength": 1024,
|
|
70
|
+
"pattern": "^(?![~/])(?!.*\\\\)(?!.*//)(?!.*(?:^|/)\\.{1,2}(?:/|$))[^\\u0000]+$"
|
|
71
|
+
},
|
|
72
|
+
"cacheReferencePath": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"pattern": "^\\.grip/cache/repos/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\.git$"
|
|
75
|
+
},
|
|
76
|
+
"stagedInputPath": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"pattern": "^\\.grip/staging/inputs/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
|
|
79
|
+
},
|
|
80
|
+
"cloneOperation": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"required": [
|
|
84
|
+
"kind",
|
|
85
|
+
"repo_url",
|
|
86
|
+
"dest_path",
|
|
87
|
+
"branch"
|
|
88
|
+
],
|
|
89
|
+
"properties": {
|
|
90
|
+
"kind": {
|
|
91
|
+
"const": "clone"
|
|
92
|
+
},
|
|
93
|
+
"repo_url": {
|
|
94
|
+
"$ref": "#/$defs/nonEmptyString"
|
|
95
|
+
},
|
|
96
|
+
"dest_path": {
|
|
97
|
+
"$ref": "#/$defs/workspaceRelativePath"
|
|
98
|
+
},
|
|
99
|
+
"branch": {
|
|
100
|
+
"$ref": "#/$defs/nonEmptyString"
|
|
101
|
+
},
|
|
102
|
+
"reference_base": {
|
|
103
|
+
"$ref": "#/$defs/cacheReferencePath"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"venvOperation": {
|
|
108
|
+
"type": "object",
|
|
109
|
+
"additionalProperties": false,
|
|
110
|
+
"required": [
|
|
111
|
+
"kind",
|
|
112
|
+
"dest_path",
|
|
113
|
+
"engine",
|
|
114
|
+
"python"
|
|
115
|
+
],
|
|
116
|
+
"properties": {
|
|
117
|
+
"kind": {
|
|
118
|
+
"const": "venv"
|
|
119
|
+
},
|
|
120
|
+
"dest_path": {
|
|
121
|
+
"$ref": "#/$defs/workspaceRelativePath"
|
|
122
|
+
},
|
|
123
|
+
"engine": {
|
|
124
|
+
"const": "uv"
|
|
125
|
+
},
|
|
126
|
+
"python": {
|
|
127
|
+
"$ref": "#/$defs/nonEmptyString"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"editableInstallOperation": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"additionalProperties": false,
|
|
134
|
+
"required": [
|
|
135
|
+
"kind",
|
|
136
|
+
"venv_path",
|
|
137
|
+
"source_path",
|
|
138
|
+
"extras"
|
|
139
|
+
],
|
|
140
|
+
"properties": {
|
|
141
|
+
"kind": {
|
|
142
|
+
"const": "editable_install"
|
|
143
|
+
},
|
|
144
|
+
"venv_path": {
|
|
145
|
+
"$ref": "#/$defs/workspaceRelativePath"
|
|
146
|
+
},
|
|
147
|
+
"source_path": {
|
|
148
|
+
"$ref": "#/$defs/workspaceRelativePath"
|
|
149
|
+
},
|
|
150
|
+
"extras": {
|
|
151
|
+
"type": "array",
|
|
152
|
+
"uniqueItems": true,
|
|
153
|
+
"items": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"minLength": 1,
|
|
156
|
+
"maxLength": 128,
|
|
157
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"projectFileOperation": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"additionalProperties": false,
|
|
165
|
+
"required": [
|
|
166
|
+
"kind",
|
|
167
|
+
"source_path",
|
|
168
|
+
"source_sha256",
|
|
169
|
+
"dest_path",
|
|
170
|
+
"mode"
|
|
171
|
+
],
|
|
172
|
+
"properties": {
|
|
173
|
+
"kind": {
|
|
174
|
+
"const": "project_file"
|
|
175
|
+
},
|
|
176
|
+
"source_path": {
|
|
177
|
+
"$ref": "#/$defs/stagedInputPath"
|
|
178
|
+
},
|
|
179
|
+
"source_sha256": {
|
|
180
|
+
"$ref": "#/$defs/sha256"
|
|
181
|
+
},
|
|
182
|
+
"dest_path": {
|
|
183
|
+
"$ref": "#/$defs/workspaceRelativePath"
|
|
184
|
+
},
|
|
185
|
+
"mode": {
|
|
186
|
+
"const": "copy"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
gr2_overlay/__init__.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Deprecated compatibility shim: ``gr2_overlay`` was renamed to ``gr2.overlay``.
|
|
2
|
+
|
|
3
|
+
Import ``gr2.overlay`` instead. Every submodule of the real package is aliased
|
|
4
|
+
through ``sys.modules`` here, so ``gr2_overlay.units`` IS ``gr2.overlay.units``
|
|
5
|
+
(the same module object, not a parallel copy) — a consumer that has not yet
|
|
6
|
+
migrated keeps working with no behavioural drift. Removed in the release after
|
|
7
|
+
1.5.0; downstream consumers migrate to ``gr2.overlay`` before then.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib as _importlib
|
|
12
|
+
import pkgutil as _pkgutil
|
|
13
|
+
import sys as _sys
|
|
14
|
+
import warnings as _warnings
|
|
15
|
+
|
|
16
|
+
_warnings.warn(
|
|
17
|
+
"gr2_overlay is deprecated and will be removed in the release after 1.5.0; "
|
|
18
|
+
"import gr2.overlay instead.",
|
|
19
|
+
DeprecationWarning,
|
|
20
|
+
stacklevel=2,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
_real = _importlib.import_module("gr2.overlay")
|
|
24
|
+
|
|
25
|
+
# Alias every submodule so `import gr2_overlay.X` and `from gr2_overlay.X import Y`
|
|
26
|
+
# resolve to the SAME module object as gr2.overlay.X. Discovered dynamically from
|
|
27
|
+
# the real package so a new submodule is covered without editing this shim.
|
|
28
|
+
for _info in _pkgutil.iter_modules(_real.__path__):
|
|
29
|
+
_mod = _importlib.import_module(f"gr2.overlay.{_info.name}")
|
|
30
|
+
_sys.modules[f"{__name__}.{_info.name}"] = _mod
|
|
31
|
+
globals()[_info.name] = _mod
|
|
32
|
+
|
|
33
|
+
# Re-export the real package's declared public names (`from gr2_overlay import X`).
|
|
34
|
+
for _attr in getattr(_real, "__all__", ()):
|
|
35
|
+
globals()[_attr] = getattr(_real, _attr)
|
|
36
|
+
|
|
37
|
+
del _importlib, _pkgutil, _sys, _warnings, _info, _mod, _real
|