polygit 0.3.4__tar.gz → 0.5.0__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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: polygit
3
- Version: 0.3.4
3
+ Version: 0.5.0
4
4
  Summary: Manage multiple git repos from a single .pgit config file.
5
5
  Project-URL: Repository, https://github.com/gschaetz/polygit
6
6
  Author-email: Gary Schaetz <gary@schaetzkc.com>
@@ -87,6 +87,29 @@ pgit push --all # one message for all dirty repos
87
87
  pgit push --wip # auto-commit with "WIP <timestamp>"
88
88
  ```
89
89
 
90
+ ## dry run
91
+
92
+ ```bash
93
+ pgit pull --dry-run # show ahead/behind per repo; changes nothing
94
+ pgit push --dry-run # list dirty repos that would be committed and pushed
95
+ ```
96
+
97
+ `pull --dry-run` compares against the last fetched state of each upstream, so run `pgit sync` first for current numbers.
98
+
99
+ ## status --json
100
+
101
+ ```bash
102
+ pgit status --json # machine-readable list of dirty repos
103
+ ```
104
+
105
+ Prints a single JSON array on stdout and nothing else:
106
+
107
+ ```json
108
+ [{"platform": "github", "path": "gschaetz/mousehat", "changed_files": 2}]
109
+ ```
110
+
111
+ `changed_files` is the number of entries in `git status --short`. Clean repos are omitted, so the array is empty when there is nothing to commit.
112
+
90
113
  ## repos — drift detection
91
114
 
92
115
  `pgit repos` compares what's actually on disk against your `.pgit` config and reports:
@@ -54,6 +54,29 @@ pgit push --all # one message for all dirty repos
54
54
  pgit push --wip # auto-commit with "WIP <timestamp>"
55
55
  ```
56
56
 
57
+ ## dry run
58
+
59
+ ```bash
60
+ pgit pull --dry-run # show ahead/behind per repo; changes nothing
61
+ pgit push --dry-run # list dirty repos that would be committed and pushed
62
+ ```
63
+
64
+ `pull --dry-run` compares against the last fetched state of each upstream, so run `pgit sync` first for current numbers.
65
+
66
+ ## status --json
67
+
68
+ ```bash
69
+ pgit status --json # machine-readable list of dirty repos
70
+ ```
71
+
72
+ Prints a single JSON array on stdout and nothing else:
73
+
74
+ ```json
75
+ [{"platform": "github", "path": "gschaetz/mousehat", "changed_files": 2}]
76
+ ```
77
+
78
+ `changed_files` is the number of entries in `git status --short`. Clean repos are omitted, so the array is empty when there is nothing to commit.
79
+
57
80
  ## repos — drift detection
58
81
 
59
82
  `pgit repos` compares what's actually on disk against your `.pgit` config and reports:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "polygit"
7
- version = "0.3.4"
7
+ version = "0.5.0"
8
8
  description = "Manage multiple git repos from a single .pgit config file."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE.txt" }
@@ -13,8 +13,12 @@ def main():
13
13
  sub = parser.add_subparsers(dest="command", metavar="command")
14
14
 
15
15
  sub.add_parser("sync", help="Clone missing repos and fetch all")
16
- sub.add_parser("status", help="Show repos with uncommitted changes")
17
- sub.add_parser("pull", help="Pull all repos, auto-stashing local changes")
16
+ status_p = sub.add_parser("status", help="Show repos with uncommitted changes")
17
+ status_p.add_argument("--json", action="store_true",
18
+ help="Print dirty repos as a JSON list")
19
+ pull_p = sub.add_parser("pull", help="Pull all repos, auto-stashing local changes")
20
+ pull_p.add_argument("--dry-run", action="store_true",
21
+ help="Show ahead/behind vs. last-fetched upstream; changes nothing")
18
22
 
19
23
  push_p = sub.add_parser("push", help="Commit and push dirty repos")
20
24
  mode_g = push_p.add_mutually_exclusive_group()
@@ -25,6 +29,8 @@ def main():
25
29
  mode_g.add_argument("--wip", dest="push_mode", action="store_const",
26
30
  const="wip", help='Auto-commit with "WIP <timestamp>"')
27
31
  push_p.set_defaults(push_mode="interactive")
32
+ push_p.add_argument("--dry-run", action="store_true",
33
+ help="Show the commit/push plan without committing or pushing")
28
34
 
29
35
  sub.add_parser("repos", help="Discover drift between .pgit and the filesystem")
30
36
 
@@ -45,9 +51,9 @@ def main():
45
51
 
46
52
  commands = {
47
53
  "sync": lambda: cmd_sync(config, base),
48
- "status": lambda: cmd_status(config, base),
49
- "pull": lambda: cmd_pull(config, base),
50
- "push": lambda: cmd_push(config, base, mode=args.push_mode),
54
+ "status": lambda: cmd_status(config, base, json_output=args.json),
55
+ "pull": lambda: cmd_pull(config, base, dry_run=args.dry_run),
56
+ "push": lambda: cmd_push(config, base, mode=args.push_mode, dry_run=args.dry_run),
51
57
  "repos": lambda: cmd_repos(config, base, config_path),
52
58
  }
53
59
  commands[args.command]()
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import shutil
2
3
  import subprocess
3
4
  import sys
@@ -137,8 +138,25 @@ def _sync_one(platform, local_path, remote_path, d):
137
138
  _emit(lines)
138
139
 
139
140
 
140
- def _pull_one(platform, local_path, d):
141
+ def _pull_dry_run(label, d):
142
+ """Report ahead/behind vs. upstream without touching the repo."""
143
+ counts = subprocess.run(
144
+ ["git", "-C", str(d), "rev-list", "--left-right", "--count", "HEAD...@{u}"],
145
+ capture_output=True, text=True,
146
+ )
147
+ if counts.returncode != 0:
148
+ return [f"{WARN} {label}: no upstream branch set"]
149
+ ahead, behind = counts.stdout.split()
150
+ if ahead == "0" and behind == "0":
151
+ return [f"{OK} {_DIM}{label}{_RST}"]
152
+ return [f"{UPD} {label}: {ahead} ahead, {behind} behind"]
153
+
154
+
155
+ def _pull_one(platform, local_path, d, dry_run=False):
141
156
  label = f"{platform}/{local_path}"
157
+ if dry_run:
158
+ _emit(_pull_dry_run(label, d))
159
+ return
142
160
  lines = []
143
161
  stashed = False
144
162
  if is_dirty(d):
@@ -177,7 +195,7 @@ def cmd_sync(config, base):
177
195
  f.result()
178
196
 
179
197
 
180
- def cmd_status(config, base):
198
+ def cmd_status(config, base, json_output=False):
181
199
  results = []
182
200
 
183
201
  def _check(platform, local_path, d):
@@ -193,6 +211,15 @@ def cmd_status(config, base):
193
211
  for f in as_completed(futures):
194
212
  results.append(f.result())
195
213
 
214
+ if json_output:
215
+ entries = [
216
+ {"platform": platform, "path": local_path, "changed_files": len(output.splitlines())}
217
+ for platform, local_path, output in sorted(results)
218
+ if output
219
+ ]
220
+ print(json.dumps(entries))
221
+ return
222
+
196
223
  found_dirty = False
197
224
  for platform, local_path, output in sorted(results):
198
225
  if output:
@@ -204,15 +231,15 @@ def cmd_status(config, base):
204
231
  print(f"{OK} All repos are clean.")
205
232
 
206
233
 
207
- def cmd_pull(config, base):
234
+ def cmd_pull(config, base, dry_run=False):
208
235
  repos = list(each_existing_repo(config, base))
209
236
  with ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
210
- futures = [pool.submit(_pull_one, p, lp, d) for p, lp, _, d in repos]
237
+ futures = [pool.submit(_pull_one, p, lp, d, dry_run) for p, lp, _, d in repos]
211
238
  for f in as_completed(futures):
212
239
  f.result()
213
240
 
214
241
 
215
- def cmd_push(config, base, mode="interactive"):
242
+ def cmd_push(config, base, mode="interactive", dry_run=False):
216
243
  dirty = [
217
244
  (platform, local_path, d)
218
245
  for platform, local_path, _, d in each_existing_repo(config, base)
@@ -223,6 +250,12 @@ def cmd_push(config, base, mode="interactive"):
223
250
  print("No dirty repos to commit.")
224
251
  return
225
252
 
253
+ if dry_run:
254
+ print("Would commit and push the following dirty repos:")
255
+ for platform, local_path, _ in dirty:
256
+ print(f" {platform}/{local_path}")
257
+ return
258
+
226
259
  if mode == "wip":
227
260
  msg = f"WIP {datetime.now().strftime('%Y-%m-%d %H:%M')}"
228
261
  with ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
@@ -0,0 +1,251 @@
1
+ import json
2
+ import subprocess
3
+ import tempfile
4
+ import pytest
5
+ from pathlib import Path
6
+ from polygit.config import find_config, load_config, write_config
7
+ from polygit.repos import parse_remote_url, del_nested, _add_to_config
8
+ from polygit.repo import walk, _pull_one, cmd_push, cmd_status
9
+
10
+
11
+ # ── parse_remote_url ──────────────────────────────────────────────────────────
12
+
13
+ def test_parse_github_ssh():
14
+ platform, path = parse_remote_url("git@github.com:gschaetz/mousehat.git")
15
+ assert platform == "github"
16
+ assert path == "gschaetz/mousehat"
17
+
18
+ def test_parse_gitlab_ssh_nested():
19
+ platform, path = parse_remote_url("git@gitlab.com:gary.schaetz/private/dev-setup.git")
20
+ assert platform == "gitlab"
21
+ assert path == "gary.schaetz/private/dev-setup"
22
+
23
+ def test_parse_https():
24
+ platform, path = parse_remote_url("https://github.com/openclaw/openclaw")
25
+ assert platform == "github"
26
+ assert path == "openclaw/openclaw"
27
+
28
+ def test_parse_none():
29
+ platform, path = parse_remote_url(None)
30
+ assert platform is None
31
+ assert path is None
32
+
33
+
34
+ # ── walk ──────────────────────────────────────────────────────────────────────
35
+
36
+ def test_walk_null():
37
+ results = list(walk(None, "ns/repo"))
38
+ assert results == [("ns/repo", "ns/repo")]
39
+
40
+ def test_walk_remote_override():
41
+ results = list(walk({"remote": "other/repo"}, "ns/local"))
42
+ assert results == [("ns/local", "other/repo")]
43
+
44
+ def test_walk_nested():
45
+ node = {"a": None, "b": {"c": None}}
46
+ results = list(walk(node, "ns"))
47
+ assert ("ns/a", "ns/a") in results
48
+ assert ("ns/b/c", "ns/b/c") in results
49
+
50
+
51
+ # ── del_nested ────────────────────────────────────────────────────────────────
52
+
53
+ def test_del_nested_simple():
54
+ d = {"a": {"b": None}}
55
+ del_nested(d, ["a", "b"])
56
+ assert d == {}
57
+
58
+ def test_del_nested_preserves_siblings():
59
+ d = {"a": {"b": None, "c": None}}
60
+ del_nested(d, ["a", "b"])
61
+ assert d == {"a": {"c": None}}
62
+
63
+
64
+ # ── _add_to_config ──────────────────────────────────────────────────────────
65
+
66
+ def test_add_to_config_plain():
67
+ config = {}
68
+ _add_to_config(config, "github", "gschaetz/mousehat", "git@github.com:gschaetz/mousehat.git")
69
+ assert config == {"github": {"gschaetz": {"mousehat": None}}}
70
+
71
+ def test_add_to_config_cross_namespace_override():
72
+ # Local dir lives under a namespace unrelated to the remote org — must
73
+ # nest under the local namespace, not silently fall back to the remote's.
74
+ config = {}
75
+ _add_to_config(config, "github", "community/modelrelay", "git@github.com:ellipticmarketing/modelrelay.git")
76
+ assert config == {"github": {"community": {"modelrelay": {"remote": "ellipticmarketing/modelrelay"}}}}
77
+
78
+ def test_add_to_config_no_remote():
79
+ config = {}
80
+ _add_to_config(config, "github", "gschaetz/scratch", None)
81
+ assert config == {"github": {"gschaetz": {"scratch": None}}}
82
+
83
+
84
+ # ── find_config / write_config / load_config ──────────────────────────────────
85
+
86
+ def test_find_config_in_cwd():
87
+ with tempfile.TemporaryDirectory() as tmp:
88
+ config_path = Path(tmp) / ".pgit"
89
+ config_path.write_text("github:\n org:\n repo:\n")
90
+ found = find_config(start=tmp)
91
+ assert found == config_path
92
+
93
+ def test_find_config_walks_up():
94
+ with tempfile.TemporaryDirectory() as tmp:
95
+ config_path = Path(tmp) / ".pgit"
96
+ config_path.write_text("github:\n org:\n repo:\n")
97
+ subdir = Path(tmp) / "sub" / "dir"
98
+ subdir.mkdir(parents=True)
99
+ found = find_config(start=subdir)
100
+ assert found == config_path
101
+
102
+ def test_find_config_not_found():
103
+ with tempfile.TemporaryDirectory() as tmp:
104
+ found = find_config(start=tmp)
105
+ assert found is None
106
+
107
+ def test_write_and_load_roundtrip():
108
+ with tempfile.TemporaryDirectory() as tmp:
109
+ path = Path(tmp) / ".pgit"
110
+ data = {
111
+ "github": {
112
+ "gschaetz": {"mousehat": None, "dotfiles": None},
113
+ "community": {"openclaw": {"remote": "openclaw/openclaw"}},
114
+ }
115
+ }
116
+ write_config(data, path)
117
+ loaded = load_config(path)
118
+ assert loaded["github"]["gschaetz"]["mousehat"] is None
119
+ assert loaded["github"]["community"]["openclaw"] == {"remote": "openclaw/openclaw"}
120
+
121
+
122
+ # ── dry-run pull / push ──────────────────────────────────────────────────────
123
+
124
+ def _git(d, *args):
125
+ subprocess.run(["git", "-C", str(d), *args], check=True, capture_output=True)
126
+
127
+
128
+ def _commit(d, name):
129
+ (d / name).write_text(name)
130
+ _git(d, "add", ".")
131
+ _git(d, "-c", "user.email=t@t.com", "-c", "user.name=T", "commit", "-qm", name)
132
+
133
+
134
+ def _make_clone(tmp, ahead=0, behind=0):
135
+ """Clone of a bare origin, `ahead` commits ahead and `behind` behind it."""
136
+ origin = tmp / "origin.git"
137
+ subprocess.run(["git", "init", "-q", "--bare", "-b", "main", str(origin)], check=True)
138
+ seed = tmp / "seed"
139
+ subprocess.run(["git", "clone", "-q", str(origin), str(seed)], check=True, capture_output=True)
140
+ _commit(seed, "init")
141
+ _git(seed, "push", "-q", "origin", "HEAD:main")
142
+ d = tmp / "github" / "r"
143
+ d.parent.mkdir()
144
+ subprocess.run(["git", "clone", "-q", str(origin), str(d)], check=True, capture_output=True)
145
+ for i in range(behind):
146
+ _commit(seed, f"b{i}")
147
+ if behind:
148
+ _git(seed, "push", "-q", "origin", "HEAD:main")
149
+ _git(d, "fetch", "-q")
150
+ for i in range(ahead):
151
+ _commit(d, f"a{i}")
152
+ return d
153
+
154
+
155
+ def test_pull_dry_run_shows_ahead_behind(capsys, tmp_path):
156
+ d = _make_clone(tmp_path, ahead=2, behind=1)
157
+ _pull_one("github", "r", d, dry_run=True)
158
+ assert "2 ahead, 1 behind" in capsys.readouterr().out
159
+
160
+
161
+ def test_pull_dry_run_up_to_date(capsys, tmp_path):
162
+ d = _make_clone(tmp_path)
163
+ _pull_one("github", "r", d, dry_run=True)
164
+ out = capsys.readouterr().out
165
+ assert "github/r" in out
166
+ assert "ahead" not in out and "behind" not in out
167
+
168
+
169
+ def test_pull_dry_run_no_upstream(capsys, tmp_path):
170
+ d = tmp_path / "r"
171
+ subprocess.run(["git", "init", "-q", str(d)], check=True)
172
+ _pull_one("github", "r", d, dry_run=True)
173
+ assert "no upstream" in capsys.readouterr().out
174
+
175
+
176
+ def test_pull_dry_run_leaves_dirty_tree_alone(tmp_path):
177
+ d = _make_clone(tmp_path)
178
+ (d / "init").write_text("edited")
179
+ (d / "new.txt").write_text("x")
180
+ _pull_one("github", "r", d, dry_run=True)
181
+ assert (d / "init").read_text() == "edited"
182
+ assert (d / "new.txt").exists()
183
+ stash = subprocess.run(["git", "-C", str(d), "stash", "list"],
184
+ capture_output=True, text=True).stdout
185
+ assert stash == ""
186
+
187
+
188
+ def test_push_dry_run_lists_dirty_without_committing(capsys, tmp_path):
189
+ d = _make_clone(tmp_path)
190
+ (d / "dirty.txt").write_text("x")
191
+ cmd_push({"github": {"r": None}}, tmp_path, dry_run=True)
192
+ out = capsys.readouterr().out
193
+ assert "Would commit and push" in out
194
+ assert "github/r" in out
195
+ assert (d / "dirty.txt").exists()
196
+ log = subprocess.run(["git", "-C", str(d), "log", "--oneline"],
197
+ capture_output=True, text=True).stdout
198
+ assert len(log.splitlines()) == 1
199
+
200
+
201
+ # ── status --json ────────────────────────────────────────────────────────────
202
+
203
+ def test_status_json_lists_dirty_repos(capsys, tmp_path):
204
+ d = _make_clone(tmp_path)
205
+ (d / "init").write_text("edited")
206
+ (d / "a.txt").write_text("a")
207
+ (d / "b.txt").write_text("b")
208
+
209
+ cmd_status({"github": {"r": None}}, tmp_path, json_output=True)
210
+
211
+ payload = json.loads(capsys.readouterr().out)
212
+ assert payload == [{"platform": "github", "path": "r", "changed_files": 3}]
213
+
214
+
215
+ def test_status_json_empty_when_clean(capsys, tmp_path):
216
+ _make_clone(tmp_path)
217
+ cmd_status({"github": {"r": None}}, tmp_path, json_output=True)
218
+ assert json.loads(capsys.readouterr().out) == []
219
+
220
+
221
+ def test_status_json_omits_clean_repos(capsys, tmp_path):
222
+ _make_clone(tmp_path)
223
+ dirty = tmp_path / "github" / "other"
224
+ subprocess.run(["git", "clone", "-q", str(tmp_path / "origin.git"), str(dirty)],
225
+ check=True, capture_output=True)
226
+ (dirty / "x.txt").write_text("x")
227
+
228
+ cmd_status({"github": {"r": None, "other": None}}, tmp_path, json_output=True)
229
+
230
+ payload = json.loads(capsys.readouterr().out)
231
+ assert payload == [{"platform": "github", "path": "other", "changed_files": 1}]
232
+
233
+
234
+ def test_status_default_output_unchanged(capsys, tmp_path):
235
+ d = _make_clone(tmp_path)
236
+ (d / "dirty.txt").write_text("x")
237
+
238
+ cmd_status({"github": {"r": None}}, tmp_path)
239
+ out = capsys.readouterr().out
240
+
241
+ assert "github/r" in out
242
+ assert "dirty.txt" in out
243
+ assert out.strip()[0] != "["
244
+ with pytest.raises(ValueError):
245
+ json.loads(out)
246
+
247
+
248
+ def test_status_default_clean_message(capsys, tmp_path):
249
+ _make_clone(tmp_path)
250
+ cmd_status({"github": {"r": None}}, tmp_path)
251
+ assert "All repos are clean." in capsys.readouterr().out
@@ -1,5 +1,5 @@
1
1
  version = 1
2
- revision = 3
2
+ revision = 5
3
3
  requires-python = ">=3.8"
4
4
  resolution-markers = [
5
5
  "python_full_version >= '3.10'",
@@ -44,25 +44,41 @@ wheels = [
44
44
 
45
45
  [[package]]
46
46
  name = "iniconfig"
47
- version = "2.3.0"
47
+ version = "2.3.1"
48
48
  source = { registry = "https://pypi.org/simple" }
49
49
  resolution-markers = [
50
50
  "python_full_version >= '3.10'",
51
51
  ]
52
- sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
52
+ sdist = { url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz", hash = "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", size = 21209, upload-time = "2026-10-06T22:48:38.076Z" }
53
53
  wheels = [
54
- { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
54
+ { url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" },
55
55
  ]
56
56
 
57
57
  [[package]]
58
58
  name = "packaging"
59
59
  version = "26.2"
60
60
  source = { registry = "https://pypi.org/simple" }
61
+ resolution-markers = [
62
+ "python_full_version < '3.9'",
63
+ ]
61
64
  sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
62
65
  wheels = [
63
66
  { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
64
67
  ]
65
68
 
69
+ [[package]]
70
+ name = "packaging"
71
+ version = "26.3"
72
+ source = { registry = "https://pypi.org/simple" }
73
+ resolution-markers = [
74
+ "python_full_version >= '3.10'",
75
+ "python_full_version == '3.9.*'",
76
+ ]
77
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
78
+ wheels = [
79
+ { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
80
+ ]
81
+
66
82
  [[package]]
67
83
  name = "pluggy"
68
84
  version = "1.5.0"
@@ -80,7 +96,6 @@ name = "pluggy"
80
96
  version = "1.6.0"
81
97
  source = { registry = "https://pypi.org/simple" }
82
98
  resolution-markers = [
83
- "python_full_version >= '3.10'",
84
99
  "python_full_version == '3.9.*'",
85
100
  ]
86
101
  sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
@@ -88,9 +103,21 @@ wheels = [
88
103
  { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
89
104
  ]
90
105
 
106
+ [[package]]
107
+ name = "pluggy"
108
+ version = "1.7.0"
109
+ source = { registry = "https://pypi.org/simple" }
110
+ resolution-markers = [
111
+ "python_full_version >= '3.10'",
112
+ ]
113
+ sdist = { url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz", hash = "sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8", size = 123304, upload-time = "2026-10-15T09:50:58.343Z" }
114
+ wheels = [
115
+ { url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" },
116
+ ]
117
+
91
118
  [[package]]
92
119
  name = "polygit"
93
- version = "0.3.3"
120
+ version = "0.5.0"
94
121
  source = { editable = "." }
95
122
  dependencies = [
96
123
  { name = "pyyaml" },
@@ -111,11 +138,11 @@ dev = [{ name = "pytest", specifier = ">=8.0" }]
111
138
 
112
139
  [[package]]
113
140
  name = "pygments"
114
- version = "2.20.0"
141
+ version = "2.21.0"
115
142
  source = { registry = "https://pypi.org/simple" }
116
- sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
143
+ sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" }
117
144
  wheels = [
118
- { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
145
+ { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" },
119
146
  ]
120
147
 
121
148
  [[package]]
@@ -129,7 +156,7 @@ dependencies = [
129
156
  { name = "colorama", marker = "sys_platform == 'win32'" },
130
157
  { name = "exceptiongroup" },
131
158
  { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" } },
132
- { name = "packaging" },
159
+ { name = "packaging", version = "26.2", source = { registry = "https://pypi.org/simple" } },
133
160
  { name = "pluggy", version = "1.5.0", source = { registry = "https://pypi.org/simple" } },
134
161
  { name = "tomli" },
135
162
  ]
@@ -149,7 +176,7 @@ dependencies = [
149
176
  { name = "colorama", marker = "sys_platform == 'win32'" },
150
177
  { name = "exceptiongroup" },
151
178
  { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" } },
152
- { name = "packaging" },
179
+ { name = "packaging", version = "26.3", source = { registry = "https://pypi.org/simple" } },
153
180
  { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" } },
154
181
  { name = "pygments" },
155
182
  { name = "tomli" },
@@ -169,9 +196,9 @@ resolution-markers = [
169
196
  dependencies = [
170
197
  { name = "colorama", marker = "sys_platform == 'win32'" },
171
198
  { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
172
- { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" } },
173
- { name = "packaging" },
174
- { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" } },
199
+ { name = "iniconfig", version = "2.3.1", source = { registry = "https://pypi.org/simple" } },
200
+ { name = "packaging", version = "26.3", source = { registry = "https://pypi.org/simple" } },
201
+ { name = "pluggy", version = "1.7.0", source = { registry = "https://pypi.org/simple" } },
175
202
  { name = "pygments" },
176
203
  { name = "tomli", marker = "python_full_version < '3.11'" },
177
204
  ]
@@ -262,56 +289,74 @@ wheels = [
262
289
 
263
290
  [[package]]
264
291
  name = "tomli"
265
- version = "2.4.1"
292
+ version = "2.5.0"
266
293
  source = { registry = "https://pypi.org/simple" }
267
- sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
294
+ sdist = { url = "https://files.pythonhosted.org/packages/b0/78/9ad63712633ed3ab5cc1a648d863d7e7da371e9425e209555a0fe711b695/tomli-2.5.0.tar.gz", hash = "sha256:264507556cd8b8c8e7c6ee037cdf443a463f03f4c958e57195e3d369711b8ff6", size = 17662, upload-time = "2026-10-07T12:23:37.892Z" }
268
295
  wheels = [
269
- { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" },
270
- { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" },
271
- { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" },
272
- { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" },
273
- { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" },
274
- { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" },
275
- { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" },
276
- { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" },
277
- { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" },
278
- { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" },
279
- { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" },
280
- { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" },
281
- { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" },
282
- { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" },
283
- { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" },
284
- { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" },
285
- { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" },
286
- { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" },
287
- { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
288
- { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
289
- { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
290
- { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
291
- { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
292
- { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
293
- { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
294
- { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
295
- { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
296
- { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
297
- { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
298
- { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
299
- { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
300
- { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
301
- { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
302
- { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
303
- { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
304
- { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
305
- { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
306
- { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
307
- { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
308
- { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
309
- { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
310
- { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
311
- { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
312
- { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
313
- { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
314
- { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
296
+ { url = "https://files.pythonhosted.org/packages/22/a6/ab99b60ee52acd949684febabc3005d0045d0f66bebd9cdebd67372d26dd/tomli-2.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4dc1c1781f2f716de763d1e9a7b34c6a894e167e291c7c5d16c72f7a9538545", size = 163901, upload-time = "2026-10-07T12:22:15.601Z" },
297
+ { url = "https://files.pythonhosted.org/packages/bc/00/ee01b7ed4579180fff07142d290257f25ba786f23f3ec6005f620933c2f5/tomli-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eff8babca5a7999bc137acbc7482a8b7e17ffca5075ab41f5d770ab408c7bfef", size = 163756, upload-time = "2026-10-07T12:22:16.957Z" },
298
+ { url = "https://files.pythonhosted.org/packages/72/c2/4efebf65372f6583185f79799312109dddb61102d47e5c33dcfd1a297aca/tomli-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86665cee9c4835b7a7f1e8ec2c719b5258d4dc782887aded5a8ae7352a96843b", size = 268038, upload-time = "2026-10-07T12:22:18.135Z" },
299
+ { url = "https://files.pythonhosted.org/packages/53/07/5850468e925d898abb36038666f9c333a94d2a223e802a8ba5b6d319d23f/tomli-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e369fd63331746182360977b1892bfc215476a30d61612d732425311639f56", size = 276422, upload-time = "2026-10-07T12:22:19.567Z" },
300
+ { url = "https://files.pythonhosted.org/packages/b4/87/f293984cdcf83c054196d4fd3dad44fc68ae55b4b8c44bc76cef360c3150/tomli-2.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ad1ea345759240d6463efa0ed1c704402752e49aa21476620738d74d72d8aa1", size = 272616, upload-time = "2026-10-07T12:22:20.794Z" },
301
+ { url = "https://files.pythonhosted.org/packages/ce/ce/db582886b3c1219d3fec93ebd669332482e5aee7a91e0f7838d84f2d1759/tomli-2.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96243987194634bd411066ce40c952e108f86af04db533ecd8ac3ff2a85b1885", size = 276593, upload-time = "2026-10-07T12:22:22.12Z" },
302
+ { url = "https://files.pythonhosted.org/packages/bf/72/7619b87dea4261fc27dd7b54c4461c129c1f7d9bb7ba3aec89c797a431b8/tomli-2.5.0-cp311-cp311-win32.whl", hash = "sha256:610b27d99f28ec5f191c7064a48f3ddb179a1fe6ca73d571483ae859f57b605e", size = 101830, upload-time = "2026-10-07T12:22:23.651Z" },
303
+ { url = "https://files.pythonhosted.org/packages/1e/74/220106da34502304b6751a2a9b8a9fbca6c3fd47e737a2e2e3da7c61c9db/tomli-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:c804ae44fe7b4bab5da295e4f980a1ff04670bca9d23fe0a4e887e08ebd741a8", size = 112742, upload-time = "2026-10-07T12:22:24.972Z" },
304
+ { url = "https://files.pythonhosted.org/packages/27/99/7d9c8b41837a7773613e169504147375c157a290167aa59ad74a085f521f/tomli-2.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:cfac177ebd6236003846ea339981f71457cb6eb748f23381eb257e45092e3980", size = 109332, upload-time = "2026-10-07T12:22:26.117Z" },
305
+ { url = "https://files.pythonhosted.org/packages/52/ed/7baa86f87493646a594de388c7c1c40a39dd0461f7e9c0359cbeefc91fe8/tomli-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f4a40d03fb9f63424f0979855bdeaf44dd7696b8d59501822c10ed30ba532df", size = 164854, upload-time = "2026-10-07T12:22:27.444Z" },
306
+ { url = "https://files.pythonhosted.org/packages/a5/b1/44c0341f2224397855723c7a8a39f718ea6fcbcc3dacc66e5aeca0f334e3/tomli-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ebf8d19b17bd0daeb7b7dec81a946a439b753942fd0210d6e96c532249eea6b", size = 164074, upload-time = "2026-10-07T12:22:28.679Z" },
307
+ { url = "https://files.pythonhosted.org/packages/23/04/e2d5b7d3fba47adedb23de616c16d428ea076c79a3d8e1d95d649ffe197e/tomli-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0", size = 274274, upload-time = "2026-10-07T12:22:29.804Z" },
308
+ { url = "https://files.pythonhosted.org/packages/43/90/6090e706ff27a6f89f4a40578e3324b95c3cd8c4150868aabf33a8f414c3/tomli-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6", size = 286435, upload-time = "2026-10-07T12:22:31.297Z" },
309
+ { url = "https://files.pythonhosted.org/packages/0a/9e/a2c40768df16c408f22430afb0a73e9d7e5f79c950884954649d1146b74d/tomli-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:61ea1ebe1e55a34ea8199cc8dbff398d35027b82271c8ac4802fd3a1fd5b1bcc", size = 278119, upload-time = "2026-10-07T12:22:32.601Z" },
310
+ { url = "https://files.pythonhosted.org/packages/12/25/3c0cb485b98e9cfac495629b1c93c87ccf0b72fbe9d2689fd8fe62c6d5a3/tomli-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed53f7e89bb04f6d9e8e7799112360b0c4d5cbff067de0814c98c37c39b920f7", size = 286177, upload-time = "2026-10-07T12:22:33.745Z" },
311
+ { url = "https://files.pythonhosted.org/packages/77/8b/0144c65f0e37e51c18d04ae15c21b19431c165002d0131fe9aa8b0b8b1e8/tomli-2.5.0-cp312-cp312-win32.whl", hash = "sha256:e7ad033e27a516a233bea839cdb77b80146facb3b4f40bf02cd0cac165cdd5c2", size = 102760, upload-time = "2026-10-07T12:22:34.887Z" },
312
+ { url = "https://files.pythonhosted.org/packages/de/32/5d6d8f42fc9a05fce69354e00ff256484192f5f2fc9a2165718fa0de61ec/tomli-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd05de8c1698f8413dd7d869492693a0bf2211543b787ac78cd5e7536af1a6d7", size = 112722, upload-time = "2026-10-07T12:22:36.162Z" },
313
+ { url = "https://files.pythonhosted.org/packages/30/65/df18032218db0fb9b769fb23c8039a051f15c811993995ea04c350273a32/tomli-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:069435bd5480429b98c5e5afb02ab21c219b6f0064680671c6dc0d46817346ea", size = 109534, upload-time = "2026-10-07T12:22:37.296Z" },
314
+ { url = "https://files.pythonhosted.org/packages/42/e5/51736d70da209350969e15aca5c5ab6e2ce1ea87a0a892a6c13aec172a86/tomli-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:943276cf269e0071948d9ff697159c1735e623c1151d88abb09b74659ef0cbea", size = 163328, upload-time = "2026-10-07T12:22:38.373Z" },
315
+ { url = "https://files.pythonhosted.org/packages/ec/55/086f80dab4ab497602644274e6dea7ec5dd0b4e262e443a8ad3bb7edee2d/tomli-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:463b16086865b97facd8d0b3fb4cb7c544e3f58d2a69dc3113d6db9653fdb043", size = 162246, upload-time = "2026-10-07T12:22:39.673Z" },
316
+ { url = "https://files.pythonhosted.org/packages/aa/eb/3ecc94459f3635c92321f4e7bde571323fdb2267c50e19e3188a281eae3b/tomli-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1245a6638fc4bb0a60af38a7d45413db34a13842027c77597c712c998c62fdf0", size = 272655, upload-time = "2026-10-07T12:22:41.08Z" },
317
+ { url = "https://files.pythonhosted.org/packages/c0/d7/494fd1f0c37a621f1ad9975c2efadb523e8101f144ed6edb2e7fe64738f2/tomli-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d8bac3d603c97e6854424e5b2b5b741bdbde387e09f162fb0446812b4a8362b", size = 283595, upload-time = "2026-10-07T12:22:42.222Z" },
318
+ { url = "https://files.pythonhosted.org/packages/70/51/bb8d62b1317e6640866f6949b2d5855e5300f2c99d46de1cd245570bba65/tomli-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:21e4cae4114aba25aa0d4f85cdf486d290fb35c0954d7bba536248da64d43066", size = 276253, upload-time = "2026-10-07T12:22:43.625Z" },
319
+ { url = "https://files.pythonhosted.org/packages/66/f4/f46bd7f0763cd47de2db697dca9257c6a4adfd1a93b018cc75c8190ed5a8/tomli-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bbaefc84548d754be821bba7c4141c4787dda182f9e77f2f87b71213529efa7b", size = 283582, upload-time = "2026-10-07T12:22:44.983Z" },
320
+ { url = "https://files.pythonhosted.org/packages/ac/03/70f2bcb2923a6db37818d917e124270a7f4cfd38ea576f5aa753a91c0ef5/tomli-2.5.0-cp313-cp313-win32.whl", hash = "sha256:abdbf6313b8d9efe157edeb7ab6eae4de064b1300ad31abf73755154b30abe68", size = 102628, upload-time = "2026-10-07T12:22:46.508Z" },
321
+ { url = "https://files.pythonhosted.org/packages/dc/98/d52024bb5b0ff68b4f0d276d867f634c84a67319a7e9f6b7708a37742333/tomli-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd4dc129784e0c5335bd4e61dfcc4487499a013419e655cf2da1d091b7e0efdc", size = 113301, upload-time = "2026-10-07T12:22:47.647Z" },
322
+ { url = "https://files.pythonhosted.org/packages/6f/f2/540db3a70572a8c23a28aba3e9c358ce0ffffbafc990905c1343aa265b31/tomli-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:69491c143d2fe063046e0301e62a810bed338fa4d1ce0fd870c27dc1e09b0d84", size = 109744, upload-time = "2026-10-07T12:22:48.925Z" },
323
+ { url = "https://files.pythonhosted.org/packages/e4/49/caf6b307766eb9567664a8707e9d6be5fcc0e8903f18781c6677a60d80c7/tomli-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d3182ee2d887e507bd67319a0a61105d1dd33facc111329559a233b772c1a105", size = 162899, upload-time = "2026-10-07T12:22:50.088Z" },
324
+ { url = "https://files.pythonhosted.org/packages/d3/c8/68cfce773a2733a49c74f99d627fb461bd990756860099eac25617889585/tomli-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:521345fd1f19d45b8df87657aaa38b6f2ca3800059fadf428e7ebf479a383646", size = 162080, upload-time = "2026-10-07T12:22:51.558Z" },
325
+ { url = "https://files.pythonhosted.org/packages/7e/b2/e5bb8651fdad593f670501a7d718b1a7f73f064d44dea15e04c04dfef45d/tomli-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b", size = 273380, upload-time = "2026-10-07T12:22:52.918Z" },
326
+ { url = "https://files.pythonhosted.org/packages/8d/d2/9e2d7f8b1dfe0e2b34c245986ebd55c4c553ea4ce6c47c443b332673253f/tomli-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75", size = 283228, upload-time = "2026-10-07T12:22:54.173Z" },
327
+ { url = "https://files.pythonhosted.org/packages/ba/df/ec7b876b7b1a2718bd74a3743c076fff565b04029ba33e8f61fac262739f/tomli-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c414be4ed9d3cac80c42e348fa5a956117d1a48227f48026e31f59cb4a7671eb", size = 277189, upload-time = "2026-10-07T12:22:55.342Z" },
328
+ { url = "https://files.pythonhosted.org/packages/7d/7b/e192d9eed0b9cb80da799f4d77052297fb9a2c3cc9b19f571f56ea88add6/tomli-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9b03d7dc168353b4132965bde20feceabaa470e570c6f59660dfae59b1f9eeb3", size = 283632, upload-time = "2026-10-07T12:22:56.735Z" },
329
+ { url = "https://files.pythonhosted.org/packages/84/50/ff94454e75461d75623e47401ed323d65c10aab8fe9033242c20cd2fdf32/tomli-2.5.0-cp314-cp314-win32.whl", hash = "sha256:6f041843c4d3a37245c0c056fd955b186bf8b1fb85690cbe40b81230891dc34b", size = 103535, upload-time = "2026-10-07T12:22:58.084Z" },
330
+ { url = "https://files.pythonhosted.org/packages/54/0b/bdacf05f963bd6026ebf6eeb0beda847d1d60e03e440725c64a4e08a0afd/tomli-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:f4b653094e18f9031102d3a1da5c729c8f222d85225b18037dac621695e46e1a", size = 114621, upload-time = "2026-10-07T12:22:59.2Z" },
331
+ { url = "https://files.pythonhosted.org/packages/61/99/53f438fa6ae4f9d4ed0ddde3e7242b3bdc34b48c8f9948b72b9e9b127676/tomli-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3f89d10c1ff6a38d992c27fc8a4816af71a909e08a40ec66934240b1e74347c3", size = 111572, upload-time = "2026-10-07T12:23:00.479Z" },
332
+ { url = "https://files.pythonhosted.org/packages/b9/20/1f88f19427d380a40e90a770e087489eaafe4aeee070ae88ed2bbec00acd/tomli-2.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e9e15b4a6c7dd6b85b5fbab29488a73f1f70de516942308daa266bf0e0aeb0d4", size = 171814, upload-time = "2026-10-07T12:23:01.914Z" },
333
+ { url = "https://files.pythonhosted.org/packages/d0/56/cbe5079c9f9a54b9b3e27fc82f08f3cb36edee75561679f53d2380c801d6/tomli-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e12bbcd32897272fb05929110362ae9ff4c1b9bb26bd9e971e71dcd3275b4c3d", size = 171324, upload-time = "2026-10-07T12:23:03.18Z" },
334
+ { url = "https://files.pythonhosted.org/packages/2b/30/1d53fd3b0f1cb3ba542e345ec32c26aefdddc4e829e4f3429af8a4f27782/tomli-2.5.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20aa36de8f2cf87237143bc1fa1aae8d6612c09118f4da21c6a684db5dd1f6f9", size = 297441, upload-time = "2026-10-07T12:23:04.345Z" },
335
+ { url = "https://files.pythonhosted.org/packages/66/d9/0800acb6a111686f764c1b91ef15cc42a20a66a46013bb42220f1d2c61c1/tomli-2.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f", size = 307476, upload-time = "2026-10-07T12:23:05.671Z" },
336
+ { url = "https://files.pythonhosted.org/packages/e8/63/30a8f3cd51b5bec37f04744bad0b0dc6160df84aad4f27b0e9283d66f221/tomli-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:984012f71908165449a951de2050d52f276bfe3aa5d5f570f63ddad814370374", size = 296113, upload-time = "2026-10-07T12:23:07.202Z" },
337
+ { url = "https://files.pythonhosted.org/packages/ab/18/0b9ffc597e69c5a1e20a7823cb60d54b39a9f54e91edcb8574f022186758/tomli-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f79203b3965b4000e91808aaa7c040206093f2b8bf86f455982f2274c9ccf442", size = 307725, upload-time = "2026-10-07T12:23:08.508Z" },
338
+ { url = "https://files.pythonhosted.org/packages/ab/c7/18f8baae0b5607a60e8e19b4a7fedee43a8ff6458e3896dcbbadeeac9c22/tomli-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:91294a9fb94a75542f6e46e4a2ae709bd8d9b51134098cae5cf3bea5478b6d03", size = 108546, upload-time = "2026-10-07T12:23:09.956Z" },
339
+ { url = "https://files.pythonhosted.org/packages/72/34/4cca9739254130627bde87500b3f2b512154fe2f278efa7e2a5e10ad4bcb/tomli-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f15e3e0b835a6d68b10c86bf80a3149780498d6911c93c3ffd1861d19f9200f1", size = 117814, upload-time = "2026-10-07T12:23:11.486Z" },
340
+ { url = "https://files.pythonhosted.org/packages/7d/fb/afa530d47dd80a78fce43beac6bc6e00f84558eafcffbc6f37b21e80d056/tomli-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6664b7ae7af7294256c53960a6103077f4914cec8ff98479c352f622c6f6b2f0", size = 115188, upload-time = "2026-10-07T12:23:12.728Z" },
341
+ { url = "https://files.pythonhosted.org/packages/66/98/316fdc00f8c0939e6fe50461dd343c162d3ad51d1286eb25b7db54361d50/tomli-2.5.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a525685c2f97da40762b8695eb7aa0af4c8344ca1905c73e4e29cb04d34607dc", size = 162775, upload-time = "2026-10-07T12:23:13.941Z" },
342
+ { url = "https://files.pythonhosted.org/packages/c5/22/7b10fa5bb01c9539f53f69b619361b19350acc73657772ea7ac70ba309a8/tomli-2.5.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:9dbb18c1cfb2f6517942fc9314437f66aa06d94436ffb1f06102ef3572f35276", size = 161406, upload-time = "2026-10-07T12:23:15.215Z" },
343
+ { url = "https://files.pythonhosted.org/packages/9c/e7/1a069d86dfd20f1f84f71c63faed9f83c1d890bc06c27d82dc7d888fb573/tomli-2.5.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:752e8b1aa6a4367ef8bf6a1a1e005540f7ed055ba36d7193796812ca5404eb52", size = 273855, upload-time = "2026-10-07T12:23:16.471Z" },
344
+ { url = "https://files.pythonhosted.org/packages/ae/83/d1ef43d1687d092ab9c235455c76e6e709483b346b056f086095c7c263a5/tomli-2.5.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47300f9bf791808f77d82747691c4bb09cb14bdf3060cca99b42cdc4361d5a7", size = 284910, upload-time = "2026-10-07T12:23:18.166Z" },
345
+ { url = "https://files.pythonhosted.org/packages/cc/05/f4d9cf7de61822ece0c3873f30d291e324911c71a378b8bfe5ced13fd9f5/tomli-2.5.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:19b0dd8749f4ea2f112c5fcfb3c5248390c899d7e2e173f1d91abee1fa0ff391", size = 277723, upload-time = "2026-10-07T12:23:19.355Z" },
346
+ { url = "https://files.pythonhosted.org/packages/42/28/78262493141fa543151cf005760c3cb01d09fc28a11f993c05109902cb8c/tomli-2.5.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:57b1c3b01fab802e2899bc3d168dca320e14165e2fd9fd584760fb4ca5826859", size = 285115, upload-time = "2026-10-07T12:23:20.698Z" },
347
+ { url = "https://files.pythonhosted.org/packages/1a/b9/e1dab9a30bcb677b5cc5cee810609cfd64f24306a3055767dd3fda00b1e0/tomli-2.5.0-cp315-cp315-win32.whl", hash = "sha256:667e521b37a6c5ccaa044202c235b530f90177ffe2cd4a64ecc213c7dd535feb", size = 103475, upload-time = "2026-10-07T12:23:21.941Z" },
348
+ { url = "https://files.pythonhosted.org/packages/4c/bd/31a3790c11d6ea95fcf5e6022ac0f8d0543c9b61120b730fc481bd43d3b4/tomli-2.5.0-cp315-cp315-win_amd64.whl", hash = "sha256:d747252933c8a65ef6bd8da0fbb7ce28a90eb6119d8cd00772cd528aa07b68d5", size = 114589, upload-time = "2026-10-07T12:23:23.098Z" },
349
+ { url = "https://files.pythonhosted.org/packages/47/a2/4f6310fa699364f0e3af7ee3af88dddd9af066d33e716a0265bbe2b3ea84/tomli-2.5.0-cp315-cp315-win_arm64.whl", hash = "sha256:75dbcde8751b0a960aa3de173aa5e894d590755c6d7758b7e774c06f1dc3cbdd", size = 111493, upload-time = "2026-10-07T12:23:24.233Z" },
350
+ { url = "https://files.pythonhosted.org/packages/68/14/00853f0b396d8971107ae1921bb5b322fdee1650d2f16bf06c20adb532e5/tomli-2.5.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:2419c2a189551987b59d80e63ec355671283336f41c6b9b89462df679c7d0c57", size = 171380, upload-time = "2026-10-07T12:23:25.512Z" },
351
+ { url = "https://files.pythonhosted.org/packages/89/ad/fa6949321dadee46b27363974fb197b94c911c3b0f7a5fd26d7dc18fc2a0/tomli-2.5.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:0dc598040da8d42cf20f0be588ed7004f46db12a0ac6c32e03a59dccedaaadcd", size = 170553, upload-time = "2026-10-07T12:23:26.855Z" },
352
+ { url = "https://files.pythonhosted.org/packages/53/aa/3056c919eb3e084df3752b2cf5f865dcc04af0b27dba2f66d7b28af4633a/tomli-2.5.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49096930c8d886c9bbdab62d2d0d17ce823ddeea522309a190b36245d5b49e01", size = 294428, upload-time = "2026-10-07T12:23:28.132Z" },
353
+ { url = "https://files.pythonhosted.org/packages/96/b2/faeeb5d8769ea3832021d73e892c8391eae7b4b4f8b55a789127bd8b18a9/tomli-2.5.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8ade5023067f99fe72b88accd30d0ea05a158e9e32a11f124e731ea9695313f", size = 304909, upload-time = "2026-10-07T12:23:29.381Z" },
354
+ { url = "https://files.pythonhosted.org/packages/f6/52/f094c09e73fb654b621716d019acb5d29bdfd1be01df80c281d552bda48d/tomli-2.5.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b69564772b5c8f22ea5f498dff08cfa825045b4d4c4400529000bdf818aa3b2a", size = 293220, upload-time = "2026-10-07T12:23:30.608Z" },
355
+ { url = "https://files.pythonhosted.org/packages/86/f5/0c30541078ca4b505ce3bd76ed931facbfec524dd018535d691d1af0a6d2/tomli-2.5.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8ff3a2ca028c7eee0c777f9a092038d0a594a9fa04e215f929a22c329e2cb142", size = 305705, upload-time = "2026-10-07T12:23:32.181Z" },
356
+ { url = "https://files.pythonhosted.org/packages/05/74/590e7d19d6a118fc5cc5704ff358e21d95b8573f6b9443b1519f29ca8825/tomli-2.5.0-cp315-cp315t-win32.whl", hash = "sha256:62fc1bc8eb03e3a9cadfca713d65614ed8e09d974a283295ffe3a831976b4dc5", size = 108432, upload-time = "2026-10-07T12:23:33.496Z" },
357
+ { url = "https://files.pythonhosted.org/packages/1c/b8/63a75cfb27a17c38550e44025d3a6e7be64516fd8608a3b75703bf37d81b/tomli-2.5.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f3fcbc57b1791fa6cbe5d8434179d51de12be1a4811469529f47f6e7487a2571", size = 117281, upload-time = "2026-10-07T12:23:34.648Z" },
358
+ { url = "https://files.pythonhosted.org/packages/72/01/e8c1debb2173973372934c68fc8e46170ab60ef23ed4592dff4dec6e8993/tomli-2.5.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d2ba24db8a9376921b5e87b4762b9adb0f3f1deaea68f2b8b0bb2c11efb9c3e7", size = 115069, upload-time = "2026-10-07T12:23:35.77Z" },
359
+ { url = "https://files.pythonhosted.org/packages/60/3f/3e3f8fd0919249b0200c80fbc4f9a1e70be19f9883da71dfb7f8b9ab8aca/tomli-2.5.0-py3-none-any.whl", hash = "sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b", size = 14765, upload-time = "2026-10-07T12:23:36.875Z" },
315
360
  ]
316
361
 
317
362
  [[package]]
@@ -1,117 +0,0 @@
1
- import tempfile
2
- import pytest
3
- from pathlib import Path
4
- from polygit.config import find_config, load_config, write_config
5
- from polygit.repos import parse_remote_url, del_nested, _add_to_config
6
- from polygit.repo import walk
7
-
8
-
9
- # ── parse_remote_url ──────────────────────────────────────────────────────────
10
-
11
- def test_parse_github_ssh():
12
- platform, path = parse_remote_url("git@github.com:gschaetz/mousehat.git")
13
- assert platform == "github"
14
- assert path == "gschaetz/mousehat"
15
-
16
- def test_parse_gitlab_ssh_nested():
17
- platform, path = parse_remote_url("git@gitlab.com:gary.schaetz/private/dev-setup.git")
18
- assert platform == "gitlab"
19
- assert path == "gary.schaetz/private/dev-setup"
20
-
21
- def test_parse_https():
22
- platform, path = parse_remote_url("https://github.com/openclaw/openclaw")
23
- assert platform == "github"
24
- assert path == "openclaw/openclaw"
25
-
26
- def test_parse_none():
27
- platform, path = parse_remote_url(None)
28
- assert platform is None
29
- assert path is None
30
-
31
-
32
- # ── walk ──────────────────────────────────────────────────────────────────────
33
-
34
- def test_walk_null():
35
- results = list(walk(None, "ns/repo"))
36
- assert results == [("ns/repo", "ns/repo")]
37
-
38
- def test_walk_remote_override():
39
- results = list(walk({"remote": "other/repo"}, "ns/local"))
40
- assert results == [("ns/local", "other/repo")]
41
-
42
- def test_walk_nested():
43
- node = {"a": None, "b": {"c": None}}
44
- results = list(walk(node, "ns"))
45
- assert ("ns/a", "ns/a") in results
46
- assert ("ns/b/c", "ns/b/c") in results
47
-
48
-
49
- # ── del_nested ────────────────────────────────────────────────────────────────
50
-
51
- def test_del_nested_simple():
52
- d = {"a": {"b": None}}
53
- del_nested(d, ["a", "b"])
54
- assert d == {}
55
-
56
- def test_del_nested_preserves_siblings():
57
- d = {"a": {"b": None, "c": None}}
58
- del_nested(d, ["a", "b"])
59
- assert d == {"a": {"c": None}}
60
-
61
-
62
- # ── _add_to_config ──────────────────────────────────────────────────────────
63
-
64
- def test_add_to_config_plain():
65
- config = {}
66
- _add_to_config(config, "github", "gschaetz/mousehat", "git@github.com:gschaetz/mousehat.git")
67
- assert config == {"github": {"gschaetz": {"mousehat": None}}}
68
-
69
- def test_add_to_config_cross_namespace_override():
70
- # Local dir lives under a namespace unrelated to the remote org — must
71
- # nest under the local namespace, not silently fall back to the remote's.
72
- config = {}
73
- _add_to_config(config, "github", "community/modelrelay", "git@github.com:ellipticmarketing/modelrelay.git")
74
- assert config == {"github": {"community": {"modelrelay": {"remote": "ellipticmarketing/modelrelay"}}}}
75
-
76
- def test_add_to_config_no_remote():
77
- config = {}
78
- _add_to_config(config, "github", "gschaetz/scratch", None)
79
- assert config == {"github": {"gschaetz": {"scratch": None}}}
80
-
81
-
82
- # ── find_config / write_config / load_config ──────────────────────────────────
83
-
84
- def test_find_config_in_cwd():
85
- with tempfile.TemporaryDirectory() as tmp:
86
- config_path = Path(tmp) / ".pgit"
87
- config_path.write_text("github:\n org:\n repo:\n")
88
- found = find_config(start=tmp)
89
- assert found == config_path
90
-
91
- def test_find_config_walks_up():
92
- with tempfile.TemporaryDirectory() as tmp:
93
- config_path = Path(tmp) / ".pgit"
94
- config_path.write_text("github:\n org:\n repo:\n")
95
- subdir = Path(tmp) / "sub" / "dir"
96
- subdir.mkdir(parents=True)
97
- found = find_config(start=subdir)
98
- assert found == config_path
99
-
100
- def test_find_config_not_found():
101
- with tempfile.TemporaryDirectory() as tmp:
102
- found = find_config(start=tmp)
103
- assert found is None
104
-
105
- def test_write_and_load_roundtrip():
106
- with tempfile.TemporaryDirectory() as tmp:
107
- path = Path(tmp) / ".pgit"
108
- data = {
109
- "github": {
110
- "gschaetz": {"mousehat": None, "dotfiles": None},
111
- "community": {"openclaw": {"remote": "openclaw/openclaw"}},
112
- }
113
- }
114
- write_config(data, path)
115
- loaded = load_config(path)
116
- assert loaded["github"]["gschaetz"]["mousehat"] is None
117
- assert loaded["github"]["community"]["openclaw"] == {"remote": "openclaw/openclaw"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes