fastws-cli 0.0.22__tar.gz → 0.0.23__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
1
  Metadata-Version: 2.4
2
2
  Name: fastws-cli
3
- Version: 0.0.22
3
+ Version: 0.0.23
4
4
  Summary: Fast workspace tools for multi-repo management
5
5
  Author: Jeremy Howard
6
6
  License-Expression: Apache-2.0
@@ -99,7 +99,7 @@ Keep `repos.txt` tracked in the workspace Git repo. Put personal additions in a
99
99
 
100
100
  `--repos-file myrepos.txt` uses `myrepos-local.txt` alongside it. Either list may be absent. Removing a repo from the baseline does not delete its checkout. The next sync discovers an existing root checkout as a personal addition. External checkouts also remain on disk; add them to the local list to keep managing them.
101
101
 
102
- The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the repo extras managed above. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
102
+ The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the managed repo extras, workspace exclusions, and build-isolation list. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
103
103
 
104
104
  ```gitignore
105
105
  /repos-local.txt
@@ -240,7 +240,7 @@ Fastws maintains `tool.uv.workspace.exclude`. It excludes unlisted top-level dir
240
240
 
241
241
  Existing globs, entries for missing directories, and entries for checkouts that are still not Python projects are retained. Use `exclude = [...]` under `[tool.fastws]` to specify exclusions the scan cannot infer, such as keeping a valid project out of the workspace. Adding members preserves hand-written `[tool.uv.sources]` entries, including path and Git sources.
242
242
 
243
- Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
243
+ Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members, except a crate marked `publish = false`, which never comes from crates.io. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
244
244
 
245
245
  Do not commit a `Cargo.lock` generated under these patches. Its source-less local entries cannot be resolved on another machine.
246
246
 
@@ -252,6 +252,8 @@ Each sync updates `workspaces` in the root `package.json`. It creates the file w
252
252
 
253
253
  An optional tracked `package.json.shared` is merged into the root `package.json` on every sync. Object-valued fields merge one level deep, shared values win conflicts, and arrays replace rather than concatenate. Unrelated local settings remain; removing a shared key does not delete its local value. Workspace discovery still manages `workspaces`. Use this file for shared policy such as version-pinned npm `allowScripts` approvals.
254
254
 
255
+ Before `uv sync`, fastws regenerates `tool.uv.no-build-isolation-package` with the sorted package names of projects using `fastws.build_backend`, including external checkouts. These builds use the shared environment's `fastws-cli` and `maturin`. Leave global build isolation enabled for other projects.
256
+
255
257
  After `uv sync`, fastws runs `cargo develop` in each mixed Rust/Python project. Cargo skips unchanged compilation inputs. These projects should keep only packaging inputs in `tool.uv.cache-keys`; Rust source changes are handled by Cargo rather than triggering a separate maturin editable build. Maturin packages with `bindings = "bin"` keep their existing uv installation path.
256
258
 
257
259
  Fastws then runs `<tool> install` at the workspace root. It runs `<tool> run build` in each JavaScript package containing both `Cargo.toml` and a `build` script. Cargo handles incremental compilation. Other build steps still run.
@@ -74,7 +74,7 @@ Keep `repos.txt` tracked in the workspace Git repo. Put personal additions in a
74
74
 
75
75
  `--repos-file myrepos.txt` uses `myrepos-local.txt` alongside it. Either list may be absent. Removing a repo from the baseline does not delete its checkout. The next sync discovers an existing root checkout as a personal addition. External checkouts also remain on disk; add them to the local list to keep managing them.
76
76
 
77
- The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the repo extras managed above. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
77
+ The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the managed repo extras, workspace exclusions, and build-isolation list. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
78
78
 
79
79
  ```gitignore
80
80
  /repos-local.txt
@@ -215,7 +215,7 @@ Fastws maintains `tool.uv.workspace.exclude`. It excludes unlisted top-level dir
215
215
 
216
216
  Existing globs, entries for missing directories, and entries for checkouts that are still not Python projects are retained. Use `exclude = [...]` under `[tool.fastws]` to specify exclusions the scan cannot infer, such as keeping a valid project out of the workspace. Adding members preserves hand-written `[tool.uv.sources]` entries, including path and Git sources.
217
217
 
218
- Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
218
+ Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members, except a crate marked `publish = false`, which never comes from crates.io. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
219
219
 
220
220
  Do not commit a `Cargo.lock` generated under these patches. Its source-less local entries cannot be resolved on another machine.
221
221
 
@@ -227,6 +227,8 @@ Each sync updates `workspaces` in the root `package.json`. It creates the file w
227
227
 
228
228
  An optional tracked `package.json.shared` is merged into the root `package.json` on every sync. Object-valued fields merge one level deep, shared values win conflicts, and arrays replace rather than concatenate. Unrelated local settings remain; removing a shared key does not delete its local value. Workspace discovery still manages `workspaces`. Use this file for shared policy such as version-pinned npm `allowScripts` approvals.
229
229
 
230
+ Before `uv sync`, fastws regenerates `tool.uv.no-build-isolation-package` with the sorted package names of projects using `fastws.build_backend`, including external checkouts. These builds use the shared environment's `fastws-cli` and `maturin`. Leave global build isolation enabled for other projects.
231
+
230
232
  After `uv sync`, fastws runs `cargo develop` in each mixed Rust/Python project. Cargo skips unchanged compilation inputs. These projects should keep only packaging inputs in `tool.uv.cache-keys`; Rust source changes are handled by Cargo rather than triggering a separate maturin editable build. Maturin packages with `bindings = "bin"` keep their existing uv installation path.
231
233
 
232
234
  Fastws then runs `<tool> install` at the workspace root. It runs `<tool> run build` in each JavaScript package containing both `Cargo.toml` and a `build` script. Cargo handles incremental compilation. Other build steps still run.
@@ -1,4 +1,5 @@
1
- __version__ = "0.0.22"
1
+ __version__ = "0.0.23"
2
+
2
3
 
3
4
 
4
5
 
@@ -59,12 +59,12 @@ def develop(root):
59
59
  lib, = [f for f in artifact['filenames'] if Path(f).suffix in ('.dylib', '.so', '.dll')]
60
60
  module = cfg.get('module-name', artifact['target']['name'])
61
61
  dest = root/cfg['python-source']/Path(*module.split('.'))
62
- paths = [replace(lib, dest.with_name(dest.name + sysconfig.get_config_var('EXT_SUFFIX')))]
62
+ replace(lib, dest.with_name(dest.name + sysconfig.get_config_var('EXT_SUFFIX')))
63
63
  if binaries:
64
64
  env = Path(os.environ.get('VIRTUAL_ENV', sys.prefix))
65
65
  scripts = env/('Scripts' if os.name == 'nt' else 'bin')
66
- paths += [replace(m['executable'], scripts/Path(m['executable']).name) for m in artifacts if m.get('executable')]
67
- return paths
66
+ for m in artifacts:
67
+ if m.get('executable'): replace(m['executable'], scripts/Path(m['executable']).name)
68
68
 
69
69
 
70
70
  def stage_binaries(root, profile=None, target=None):
@@ -172,7 +172,7 @@ def _remove_from_pyproject(pyproject_path: Path, names: list[str]) -> list[str]:
172
172
  sources = {k:v for k,v in sources.items() if _pkg_key(k) not in targets}
173
173
  deps = [d for d in deps if _pkg_key(dep_key(d)) not in targets]
174
174
  content = _replace_table(content, "tool.uv.sources", "\n".join(f"{k} = {_fmt_source(v)}" for k,v in sources.items()))
175
- content = _replace_project_dependencies(content, deps)
175
+ content = _replace_array(content, "project", "dependencies", deps)
176
176
  pyproject_path.write_text(content)
177
177
  return removed
178
178
 
@@ -247,17 +247,17 @@ def _sync_ws_excludes(pyproject_path: Path, root: Path, tracked: set[str]) -> tu
247
247
  survivors = set(kept) | set(auto)
248
248
  new = [e for e in cur if e in survivors] + [e for e in kept + auto if e not in cur]
249
249
  if new == cur: return [], []
250
- content = _replace_ws_excludes(content, new)
250
+ content = _replace_array(content, "tool.uv.workspace", "exclude", new)
251
251
  tomllib.loads(content) # never write an unparseable pyproject
252
252
  pyproject_path.write_text(content)
253
253
  return [e for e in new if e not in cur], [e for e in cur if e not in new]
254
254
 
255
- def _replace_ws_excludes(content: str, excludes: list[str]) -> str:
256
- block = "exclude = [\n" + "".join(f' "{e}",\n' for e in excludes) + "]"
257
- if not (span := _table_span(content, "tool.uv.workspace")): return content.rstrip() + "\n\n[tool.uv.workspace]\n" + block + "\n"
255
+ def _replace_array(content: str, table: str, key: str, values: list[str]) -> str:
256
+ block = f"{key} = [\n" + "".join(f' {json.dumps(v)},\n' for v in values) + "]"
257
+ if not (span := _table_span(content, table)): return _replace_table(content, table, block)
258
258
  start,end = span
259
259
  section = content[start:end]
260
- if m := re.search(r"(?m)^exclude\s*=\s*\[", section):
260
+ if m := re.search(rf"(?m)^{re.escape(key)}\s*=\s*\[", section):
261
261
  arr_start = m.end()-1
262
262
  arr_end = _find_array_end(section, arr_start)
263
263
  section = section[:m.start()] + block + section[arr_end+1:]
@@ -293,18 +293,6 @@ def _find_array_end(content: str, start: int) -> int:
293
293
  if depth == 0: return i
294
294
  raise ValueError("Unterminated TOML array")
295
295
 
296
- def _replace_project_dependencies(content: str, deps: list[str]) -> str:
297
- if not (span := _table_span(content, "project")): raise SystemExit("Missing [project] table in pyproject.toml")
298
- start,end = span
299
- section = content[start:end]
300
- dep_block = "dependencies = [\n" + "".join(f' {json.dumps(dep)},\n' for dep in deps) + "]"
301
- if m := re.search(r"(?m)^dependencies\s*=\s*\[", section):
302
- arr_start = m.end()-1
303
- arr_end = _find_array_end(section, arr_start)
304
- section = section[:m.start()] + dep_block + section[arr_end+1:]
305
- else: section = section.rstrip() + "\n" + dep_block + "\n"
306
- return content[:start] + section + content[end:]
307
-
308
296
  def _init_ws_pyproject(path: Path, python: str = f"{sys.version_info.major}.{sys.version_info.minor}") -> bool:
309
297
  if path.exists(): return False
310
298
  major,minor = map(int, python.split(".")[:2])
@@ -348,10 +336,21 @@ def _sync_ws_pyproject(pyproject_path: Path, template_path: Path, projects: list
348
336
  if missing or ext_missing:
349
337
  source_lines = "\n".join(f"{proj} = {_fmt_source(src)}" for proj,src in sources.items())
350
338
  content = _replace_table(content, "tool.uv.sources", source_lines)
351
- if deps != data.get("project", {}).get("dependencies", []): content = _replace_project_dependencies(content, deps)
339
+ if deps != data.get("project", {}).get("dependencies", []): content = _replace_array(content, "project", "dependencies", deps)
352
340
  if content != original: pyproject_path.write_text(content)
353
341
  return missing + [n for n,_ in ext_missing]
354
342
 
343
+ def _sync_build_isolation(pyproject_path: Path, projects: list[tuple[str, Path]]):
344
+ "Regenerate uv's non-isolated build list from the projects using the fastws backend."
345
+ content = pyproject_path.read_text()
346
+ packages = sorted({name for name,d in projects
347
+ if tomllib.loads((d/'pyproject.toml').read_text()).get('build-system', {}).get('build-backend') == 'fastws.build_backend'})
348
+ current = tomllib.loads(content).get('tool', {}).get('uv', {}).get('no-build-isolation-package', [])
349
+ if packages == current: return
350
+ content = _replace_array(content, 'tool.uv', 'no-build-isolation-package', packages)
351
+ tomllib.loads(content)
352
+ pyproject_path.write_text(content)
353
+
355
354
  def _editable_mapping(path: Path) -> dict[str,str]:
356
355
  tree = ast.parse(path.read_text(), filename=str(path))
357
356
  for node in tree.body:
@@ -564,7 +563,7 @@ def cargo_develop(
564
563
  ):
565
564
  r"Build and install a mixed Rust/Python project's extension and opted-in binaries."
566
565
  from .cargo import develop
567
- for dest in develop(Path(path).resolve()): pass
566
+ develop(Path(path).resolve())
568
567
 
569
568
  @call_parse(pos=['command'])
570
569
  def cargo_stage(
@@ -645,18 +644,18 @@ def _cargo_patches(root: Path):
645
644
  return patches, config
646
645
 
647
646
  def _crate_pkgs(d: Path):
648
- "(package name, dir) for the crate at `d` and its cargo workspace members"
647
+ "(`[package]` table, dir) for the crate at `d` and its cargo workspace members"
649
648
  try: data = tomllib.loads((d/"Cargo.toml").read_text())
650
649
  except tomllib.TOMLDecodeError: return
651
- if name := data.get("package", {}).get("name"): yield name, d
650
+ if "name" in (pkg := data.get("package", {})): yield pkg, d
652
651
  for m in _project_dirs(d, "Cargo.toml", data.get("workspace", {}).get("members", [])):
653
652
  try: sub = tomllib.loads((m/"Cargo.toml").read_text())
654
653
  except tomllib.TOMLDecodeError: continue
655
- if name := sub.get("package", {}).get("name"): yield name, m
654
+ if "name" in (pkg := sub.get("package", {})): yield pkg, m
656
655
 
657
- def _local_crates(root: Path) -> dict[str, Path]:
658
- "Package name -> dir for every crate under `root`, nested cargo workspace members included"
659
- return {name: d for crate in _crate_dirs(root) for name, d in _crate_pkgs(crate)}
656
+ def _local_crates(root: Path) -> list[tuple[dict, Path]]:
657
+ "(`[package]` table, dir) for every crate under `root`, nested cargo workspace members included"
658
+ return [p for crate in _crate_dirs(root) for p in _crate_pkgs(crate)]
660
659
 
661
660
  def _git_dep_tables(root: Path, crates: dict[str, Path]) -> dict[str, dict[str, Path]]:
662
661
  "Git URL -> {package: local dir} for members' git deps that name a local crate"
@@ -688,14 +687,15 @@ def _entry_changes(current, new):
688
687
  def _sync_cargo_patches(root: Path) -> tuple[list[str], list[str]]:
689
688
  """Regenerate `[patch]` entries in the workspace `.cargo/config.toml` and return (added, removed).
690
689
 
691
- Every local crate gets a `[patch.crates-io]` entry, and a member's git dep on a local crate gets
692
- an entry under that URL, so builds anywhere under `root` use the checkouts: the cargo analog of
693
- editable installs. Only entries whose path is inside `root` are managed; entries pointing
694
- elsewhere (and any other config sections) are kept as-is, and a kept entry wins over a generated
695
- one of the same name."""
690
+ Every local crate gets a `[patch.crates-io]` entry, except one marked `publish = false`, which never comes
691
+ from crates.io. A member's git dep on a local crate gets an entry under that URL. Builds anywhere under `root`
692
+ then use the checkouts: the cargo analog of editable installs. Only entries whose path is inside `root` are
693
+ managed; entries pointing elsewhere (and any other config sections) are kept as-is, and a kept entry wins
694
+ over a generated one of the same name."""
696
695
  root = root.resolve()
697
- crates = _local_crates(root)
698
- desired = {"crates-io": {name: str(d) for name, d in crates.items()}}
696
+ pkgs = _local_crates(root)
697
+ crates = {pkg["name"]: d for pkg, d in pkgs}
698
+ desired = {"crates-io": {pkg["name"]: str(d) for pkg, d in pkgs if pkg.get("publish") is not False}}
699
699
  for url, entries in _git_dep_tables(root, crates).items(): desired[url] = {name: str(d) for name, d in entries.items()}
700
700
  config = root/".cargo"/"config.toml"
701
701
  content = config.read_text() if config.exists() else ""
@@ -923,6 +923,8 @@ async def ws_sync(
923
923
  missing_projects = _sync_ws_pyproject(pyproject_path, template_path, _ws_projects(root), _external_projects(root, ext_dirs),
924
924
  _repo_extras(root, entries))
925
925
  if missing_projects: print(f"Added workspace projects: {', '.join(missing_projects)}")
926
+ projects = _build_projects(root, repos_file)
927
+ _sync_build_isolation(pyproject_path, projects)
926
928
 
927
929
  wrapper_added = _sync_cargo_wrapper(root)
928
930
  added_p, removed_p = _sync_cargo_patches(root)
@@ -943,7 +945,7 @@ async def ws_sync(
943
945
  if up: _cargo_update(root, workers=workers)
944
946
  _sync_cargo_keys(root)
945
947
  subprocess.run(["uv", "sync", "-U"] if up else ["uv", "sync"], check=True, cwd=root)
946
- for _,d in _build_projects(root, repos_file):
948
+ for _,d in projects:
947
949
  cfg = tomllib.loads((d/'pyproject.toml').read_text()).get('tool', {}).get('maturin', {})
948
950
  if 'python-source' in cfg and cfg.get('bindings') != 'bin': cargo_develop(path=str(d))
949
951
  if up: _upgrade_stamp(root).touch()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastws-cli
3
- Version: 0.0.22
3
+ Version: 0.0.23
4
4
  Summary: Fast workspace tools for multi-repo management
5
5
  Author: Jeremy Howard
6
6
  License-Expression: Apache-2.0
@@ -99,7 +99,7 @@ Keep `repos.txt` tracked in the workspace Git repo. Put personal additions in a
99
99
 
100
100
  `--repos-file myrepos.txt` uses `myrepos-local.txt` alongside it. Either list may be absent. Removing a repo from the baseline does not delete its checkout. The next sync discovers an existing root checkout as a personal addition. External checkouts also remain on disk; add them to the local list to keep managing them.
101
101
 
102
- The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the repo extras managed above. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
102
+ The workspace `pyproject.toml` is local generated state. `ws-sync` creates it from the tracked `pyproject.tmpl` when available, or generates a minimal one, then maintains it while preserving personal settings except for the managed repo extras, workspace exclusions, and build-isolation list. The template supplies starting defaults only: later template edits do not overwrite existing configuration. Ignore these files in the workspace repo (not in its member repos):
103
103
 
104
104
  ```gitignore
105
105
  /repos-local.txt
@@ -240,7 +240,7 @@ Fastws maintains `tool.uv.workspace.exclude`. It excludes unlisted top-level dir
240
240
 
241
241
  Existing globs, entries for missing directories, and entries for checkouts that are still not Python projects are retained. Use `exclude = [...]` under `[tool.fastws]` to specify exclusions the scan cannot infer, such as keeping a valid project out of the workspace. Adding members preserves hand-written `[tool.uv.sources]` entries, including path and Git sources.
242
242
 
243
- Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
243
+ Each sync regenerates Cargo overrides in the workspace's `.cargo/config.toml`. `[patch.crates-io]` gets an entry for each local crate, including nested Cargo workspace members, except a crate marked `publish = false`, which never comes from crates.io. Git dependencies that name local crates get entries under the matching URL. Builds under the workspace root use these local checkouts. Entries pointing outside the root and other configuration sections are preserved.
244
244
 
245
245
  Do not commit a `Cargo.lock` generated under these patches. Its source-less local entries cannot be resolved on another machine.
246
246
 
@@ -252,6 +252,8 @@ Each sync updates `workspaces` in the root `package.json`. It creates the file w
252
252
 
253
253
  An optional tracked `package.json.shared` is merged into the root `package.json` on every sync. Object-valued fields merge one level deep, shared values win conflicts, and arrays replace rather than concatenate. Unrelated local settings remain; removing a shared key does not delete its local value. Workspace discovery still manages `workspaces`. Use this file for shared policy such as version-pinned npm `allowScripts` approvals.
254
254
 
255
+ Before `uv sync`, fastws regenerates `tool.uv.no-build-isolation-package` with the sorted package names of projects using `fastws.build_backend`, including external checkouts. These builds use the shared environment's `fastws-cli` and `maturin`. Leave global build isolation enabled for other projects.
256
+
255
257
  After `uv sync`, fastws runs `cargo develop` in each mixed Rust/Python project. Cargo skips unchanged compilation inputs. These projects should keep only packaging inputs in `tool.uv.cache-keys`; Rust source changes are handled by Cargo rather than triggering a separate maturin editable build. Maturin packages with `bindings = "bin"` keep their existing uv installation path.
256
258
 
257
259
  Fastws then runs `<tool> install` at the workspace root. It runs `<tool> run build` in each JavaScript package containing both `Cargo.toml` and a `build` script. Cargo handles incremental compilation. Other build steps still run.
@@ -155,17 +155,17 @@ def test_sync_cargo_patches_generates_and_preserves(tmp_path):
155
155
  (crate1/'Cargo.toml').write_text('[package]\nname = "crate1"\nversion = "0.1.0"\n\n[dependencies]\nfamily = { git = "https://example.com/family" }\n')
156
156
  family = tmp_path/'family'
157
157
  (family/'sub').mkdir(parents=True)
158
- (family/'Cargo.toml').write_text('[package]\nname = "family"\nversion = "0.1.0"\n\n[workspace]\nmembers = ["sub"]\n')
158
+ (family/'Cargo.toml').write_text('[package]\nname = "family"\nversion = "0.1.0"\npublish = false\n\n[workspace]\nmembers = ["sub"]\n')
159
159
  (family/'sub'/'Cargo.toml').write_text('[package]\nname = "family-sub"\nversion = "0.1.0"\n')
160
160
 
161
161
  added, removed = core._sync_cargo_patches(tmp_path)
162
162
  data = core.tomllib.loads(config.read_text())
163
163
  cio = data['patch']['crates-io']
164
- assert set(cio) == {'foreign', 'crate1', 'family', 'family-sub'}
164
+ assert set(cio) == {'foreign', 'crate1', 'family-sub'} # `publish = false` crates never come from crates.io
165
165
  assert cio['foreign']['path'] == '/elsewhere/foreign' # entries pointing outside the root are kept as-is
166
166
  assert cio['crate1']['path'] == str(crate1)
167
167
  assert cio['family-sub']['path'] == str(family/'sub')
168
- assert data['patch']['https://example.com/family']['family']['path'] == str(family) # git deps on local crates get their URL table
168
+ assert data['patch']['https://example.com/family']['family']['path'] == str(family) # git deps on local crates get their URL table, published or not
169
169
  assert data['term']['quiet'] is True # other sections untouched
170
170
  assert set(added) == {'crate1', 'family', 'family-sub'} and removed == ['gone']
171
171
 
File without changes
File without changes
File without changes