cpdocs 0.2.0__tar.gz → 0.3.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.
Files changed (152) hide show
  1. {cpdocs-0.2.0 → cpdocs-0.3.0}/PKG-INFO +1 -1
  2. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/cli.md +5 -4
  3. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/__init__.py +1 -1
  4. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/build.py +11 -6
  5. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/cli.py +12 -2
  6. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/properdocs_plugin.py +11 -0
  7. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_build.py +21 -0
  8. {cpdocs-0.2.0 → cpdocs-0.3.0}/.github/workflows/docs.yml +0 -0
  9. {cpdocs-0.2.0 → cpdocs-0.3.0}/.github/workflows/test.yml +0 -0
  10. {cpdocs-0.2.0 → cpdocs-0.3.0}/.gitignore +0 -0
  11. {cpdocs-0.2.0 → cpdocs-0.3.0}/LICENSES/Apache-2.0.txt +0 -0
  12. {cpdocs-0.2.0 → cpdocs-0.3.0}/REUSE.toml +0 -0
  13. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/api/index.md +0 -0
  14. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/cpdocs.yml +0 -0
  15. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/examples/index.md +0 -0
  16. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/explanation/architecture.md +0 -0
  17. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/explanation/feature-sets.md +0 -0
  18. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/how-to/ci.md +0 -0
  19. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/how-to/feature-sets.md +0 -0
  20. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/how-to/generated-headers.md +0 -0
  21. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/how-to/other-build-systems.md +0 -0
  22. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/how-to/properdocs.md +0 -0
  23. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/index.md +0 -0
  24. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/api.md +0 -0
  25. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/cmake.md +0 -0
  26. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/comments.md +0 -0
  27. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/configuration.md +0 -0
  28. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/contract.md +0 -0
  29. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/extraction.md +0 -0
  30. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/reference/links.md +0 -0
  31. {cpdocs-0.2.0 → cpdocs-0.3.0}/docs/web/tutorials/first-reference.md +0 -0
  32. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/.gitignore +0 -0
  33. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/CMakeLists.txt +0 -0
  34. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/docs/api/index.md +0 -0
  35. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/docs/cpdocs.yml +0 -0
  36. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/docs/web/api.md +0 -0
  37. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/docs/web/index.md +0 -0
  38. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/include/acme/math.hpp +0 -0
  39. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/properdocs.yml +0 -0
  40. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/readme.md +0 -0
  41. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/basic-cpp/src/math.cpp +0 -0
  42. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/.gitignore +0 -0
  43. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/CMakeLists.txt +0 -0
  44. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/docs/api/index.md +0 -0
  45. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/docs/cpdocs.yml +0 -0
  46. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/docs/web/api.md +0 -0
  47. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/docs/web/index.md +0 -0
  48. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/include/ring/ring.h +0 -0
  49. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/properdocs.yml +0 -0
  50. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/readme.md +0 -0
  51. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/c-basic/src/ring.c +0 -0
  52. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/.gitignore +0 -0
  53. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/CMakeLists.txt +0 -0
  54. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/docs/api/index.md +0 -0
  55. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/docs/cpdocs-minibuild.yml +0 -0
  56. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/docs/cpdocs.yml +0 -0
  57. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/docs/web/api.md +0 -0
  58. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/docs/web/index.md +0 -0
  59. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/include/demo/solver.hpp +0 -0
  60. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/properdocs.yml +0 -0
  61. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/readme.md +0 -0
  62. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-features/tools/minibuild.py +0 -0
  63. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/.gitignore +0 -0
  64. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/CMakeLists.txt +0 -0
  65. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/docs/api/index.md +0 -0
  66. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/docs/cpdocs.yml +0 -0
  67. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/docs/web/api.md +0 -0
  68. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/docs/web/index.md +0 -0
  69. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/include/meta/meta.hpp +0 -0
  70. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/properdocs.yml +0 -0
  71. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/cpp-templates/readme.md +0 -0
  72. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/CMakeLists.txt +0 -0
  73. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/docs/cpdocs.yml +0 -0
  74. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/docs/index.md +0 -0
  75. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/lib/normalize.f90 +0 -0
  76. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/mod/geometry.f90 +0 -0
  77. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/properdocs.yml +0 -0
  78. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/fortran-basic/readme.md +0 -0
  79. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/.gitignore +0 -0
  80. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/CMakeLists.txt +0 -0
  81. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/docs/api/index.md +0 -0
  82. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/docs/cpdocs.yml +0 -0
  83. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/docs/web/api.md +0 -0
  84. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/docs/web/index.md +0 -0
  85. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/generated-template/generated.hpp +0 -0
  86. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/include/acme/core.hpp +0 -0
  87. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/properdocs.yml +0 -0
  88. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/readme.md +0 -0
  89. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/generated-cpp/src/generated.cpp +0 -0
  90. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/.gitignore +0 -0
  91. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/CMakeLists.txt +0 -0
  92. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/docs/api/index.md +0 -0
  93. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/docs/cpdocs.yml +0 -0
  94. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/docs/web/api.md +0 -0
  95. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/docs/web/index.md +0 -0
  96. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/include/geom/vector.hpp +0 -0
  97. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/properdocs.yml +0 -0
  98. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/python/pygeom/__init__.py +0 -0
  99. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/readme.md +0 -0
  100. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/mixed/src/geom.cpp +0 -0
  101. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/.gitignore +0 -0
  102. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/docs/api/index.md +0 -0
  103. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/docs/cpdocs.yml +0 -0
  104. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/docs/web/api.md +0 -0
  105. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/docs/web/index.md +0 -0
  106. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/properdocs.yml +0 -0
  107. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/pyproject.toml +0 -0
  108. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/readme.md +0 -0
  109. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/src/dice/__init__.py +0 -0
  110. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/src/dice/_rng.py +0 -0
  111. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/python-basic/src/dice/core.py +0 -0
  112. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/Cargo.lock +0 -0
  113. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/Cargo.toml +0 -0
  114. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/docs/api.md +0 -0
  115. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/docs/cpdocs.yml +0 -0
  116. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/docs/index.md +0 -0
  117. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/properdocs.yml +0 -0
  118. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/readme.md +0 -0
  119. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/rust-toolchain.toml +0 -0
  120. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/src/geometry.rs +0 -0
  121. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/src/internal.rs +0 -0
  122. {cpdocs-0.2.0 → cpdocs-0.3.0}/examples/rust-basic/src/lib.rs +0 -0
  123. {cpdocs-0.2.0 → cpdocs-0.3.0}/properdocs.yml +0 -0
  124. {cpdocs-0.2.0 → cpdocs-0.3.0}/pyproject.toml +0 -0
  125. {cpdocs-0.2.0 → cpdocs-0.3.0}/readme.md +0 -0
  126. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/__main__.py +0 -0
  127. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/clang_backend.py +0 -0
  128. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/config.py +0 -0
  129. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/contract.py +0 -0
  130. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/fortran_backend.py +0 -0
  131. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/html_renderer.py +0 -0
  132. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/html_renderer.py.rej +0 -0
  133. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/model.py +0 -0
  134. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/properdocs_core.py +0 -0
  135. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/python_backend.py +0 -0
  136. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/python_manifest.py +0 -0
  137. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/render.py +0 -0
  138. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/rust_backend.py +0 -0
  139. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/rust_manifest.py +0 -0
  140. {cpdocs-0.2.0 → cpdocs-0.3.0}/src/cpdocs/versioning.py +0 -0
  141. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/conftest.py +0 -0
  142. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_api_reference.py +0 -0
  143. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_api_reference.py.rej +0 -0
  144. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_config.py +0 -0
  145. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_contract.py +0 -0
  146. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_examples.py +0 -0
  147. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_feature_set_signatures.py +0 -0
  148. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_properdocs_core.py +0 -0
  149. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_rust_example.py +0 -0
  150. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_rust_provider.py +0 -0
  151. {cpdocs-0.2.0 → cpdocs-0.3.0}/test/test_versioning.py +0 -0
  152. {cpdocs-0.2.0 → cpdocs-0.3.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cpdocs
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Semantic, versioned API documentation for C, C++, CUDA, HIP, Fortran, Python and Rust projects
5
5
  Project-URL: Source, https://github.com/ambhora/cpdocs
6
6
  Author-email: Jayesh Badwaik <j.badwaik@fz-juelich.de>
@@ -5,8 +5,8 @@ SPDX-License-Identifier: Apache-2.0
5
5
  # Command line
6
6
 
7
7
  ```text
8
- cpdocs build [--config docs/cpdocs.yml] [--output build] [--label main]
9
- cpdocs versions [--config docs/cpdocs.yml] [--output build]
8
+ cpdocs build [--config docs/cpdocs.yml] [--output build] [--tmp-directory DIR] [--label main]
9
+ cpdocs versions [--config docs/cpdocs.yml] [--output build] [--tmp-directory DIR]
10
10
  cpdocs manifest python feature-sets ...
11
11
  cpdocs manifest python build ...
12
12
  cpdocs rust feature-sets --source <project> --output <feature-sets.json>
@@ -26,5 +26,6 @@ declared Cargo feature is treated as a disjoint feature set and documented once;
26
26
  specific combinations can list them in `[package.metadata.cpdocs]`. `rust build` runs Cargo rustdoc
27
27
  with nightly JSON output and writes a normal cpdocs manifest.
28
28
 
29
- Feature-set inputs, manifests, scratch/build directories and command logs are kept below
30
- `<output>/cpdocs/work/<version>/feature-sets/`.
29
+ By default, feature-set inputs, manifests, scratch/build directories and command logs are kept below
30
+ `<output>/cpdocs/work/<version>/feature-sets/`. Pass `--tmp-directory DIR` to keep this workspace
31
+ under `DIR/cpdocs/work/` while leaving rendered output under `<output>/cpdocs/`.
@@ -2,4 +2,4 @@
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  """Language-neutral semantic API documentation generator."""
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.3.0"
@@ -47,13 +47,16 @@ _CONTAINER_KINDS = {"namespace", "package", "module"}
47
47
 
48
48
  @dataclasses.dataclass(frozen=True)
49
49
  class Layout:
50
- """Directories below ``<output>/cpdocs``."""
50
+ """Published and temporary directories used by cpdocs."""
51
51
 
52
52
  root: Path
53
+ work_root: Path
53
54
 
54
55
  @classmethod
55
- def for_output(cls, output: Path) -> Layout:
56
- return cls(root=(output / "cpdocs").resolve())
56
+ def for_output(cls, output: Path, *, tmp_directory: Path | None = None) -> Layout:
57
+ root = (output / "cpdocs").resolve()
58
+ work_root = (tmp_directory.resolve() / "cpdocs" if tmp_directory else root)
59
+ return cls(root=root, work_root=work_root)
57
60
 
58
61
  @property
59
62
  def current(self) -> Path:
@@ -64,7 +67,7 @@ class Layout:
64
67
  return self.root / "versions"
65
68
 
66
69
  def work(self, ref: str) -> Path:
67
- return self.root / "work" / ref.replace("/", "__")
70
+ return self.work_root / "work" / ref.replace("/", "__")
68
71
 
69
72
 
70
73
 
@@ -505,10 +508,11 @@ def build_current(
505
508
  output: Path,
506
509
  version: str = "main",
507
510
  project_docs_root_depth: int = 2,
511
+ tmp_directory: Path | None = None,
508
512
  ) -> ApiGraph:
509
513
  """Document the working tree into ``<output>/cpdocs/current``."""
510
514
 
511
- layout = Layout.for_output(output)
515
+ layout = Layout.for_output(output, tmp_directory=tmp_directory)
512
516
  work = layout.work("current")
513
517
  graph = build_graph(
514
518
  config,
@@ -610,10 +614,11 @@ def build_versions(
610
614
  output: Path,
611
615
  project_docs_root_depth: int = 2,
612
616
  include_working_tree: bool = False,
617
+ tmp_directory: Path | None = None,
613
618
  ) -> list[str]:
614
619
  """Document the explicitly configured ``versions`` in order."""
615
620
 
616
- layout = Layout.for_output(output)
621
+ layout = Layout.for_output(output, tmp_directory=tmp_directory)
617
622
  project_root = config.project_root.resolve()
618
623
  subdirectory = project_root.relative_to(_repository_root(project_root))
619
624
  selected = select_refs(project_root, config.versions)
@@ -34,6 +34,11 @@ def _parser() -> argparse.ArgumentParser:
34
34
  default=Path("build"),
35
35
  help="output root; cpdocs writes below <output>/cpdocs (default: build)",
36
36
  )
37
+ command.add_argument(
38
+ "--tmp-directory",
39
+ type=_path,
40
+ help="temporary workspace root; defaults to the output root",
41
+ )
37
42
  return command
38
43
 
39
44
  build = documentation("build", "document the working tree")
@@ -110,10 +115,15 @@ def main(argv: list[str] | None = None) -> int:
110
115
  else:
111
116
  config = load_config(arguments.config)
112
117
  output = arguments.output.resolve()
118
+ tmp_directory = (
119
+ arguments.tmp_directory.resolve() if arguments.tmp_directory is not None else None
120
+ )
113
121
  if arguments.command == "build":
114
- build_current(config, output=output, version=arguments.label)
122
+ build_current(
123
+ config, output=output, version=arguments.label, tmp_directory=tmp_directory
124
+ )
115
125
  else:
116
- build_versions(config, output=output)
126
+ build_versions(config, output=output, tmp_directory=tmp_directory)
117
127
  except RuntimeError as error:
118
128
  parser.exit(1, f"cpdocs: error: {error}\n")
119
129
  return 0
@@ -44,6 +44,7 @@ class CpdocsPlugin(BasePlugin):
44
44
  config_scheme = (
45
45
  ("config", c.Type(str, default=str(DEFAULT_CONFIG))),
46
46
  ("output", c.Type(str, default="build")),
47
+ ("tmp_directory", c.Type(str, default="")),
47
48
  ("mount", c.Type(str, default="reference/api")),
48
49
  ("subsites", c.ListOfItems(c.Type(str), default=[])),
49
50
  )
@@ -69,6 +70,15 @@ class CpdocsPlugin(BasePlugin):
69
70
  path = Path(str(self.config.get("output", "build")))
70
71
  return path if path.is_absolute() else self._project_root / path
71
72
 
73
+ @property
74
+ def tmp_directory(self) -> Path | None:
75
+ assert self._project_root is not None
76
+ value = str(self.config.get("tmp_directory", "")).strip()
77
+ if not value:
78
+ return None
79
+ path = Path(value).expanduser()
80
+ return path if path.is_absolute() else self._project_root / path
81
+
72
82
  def on_startup(self, *, command: str, dirty: bool = False) -> None:
73
83
  del dirty
74
84
  self._serve_active = command == "serve" or os.environ.get("_CPDOCS_SERVE_IN_SITU") == "1"
@@ -221,6 +231,7 @@ class CpdocsPlugin(BasePlugin):
221
231
  output=self.output,
222
232
  project_docs_root_depth=len(PurePosixPath(self.mount).parts),
223
233
  include_working_tree=self._serve_active,
234
+ tmp_directory=self.tmp_directory,
224
235
  )
225
236
  except RuntimeError as error:
226
237
  raise PluginError(f"cpdocs: {error}") from error
@@ -153,3 +153,24 @@ def test_obsolete_cpdocs_cmake_placeholder_is_rejected(tmp_path: Path) -> None:
153
153
  )
154
154
  with pytest.raises(RuntimeError, match="cpdocs-cmake"):
155
155
  build_current(load_config(config), output=project / "build")
156
+
157
+
158
+ def test_tmp_directory_separates_work_from_output(tmp_path, monkeypatch):
159
+ project = tmp_path / "project"
160
+ project.mkdir()
161
+ config_file = project / "cpdocs.yml"
162
+ config_file.write_text(
163
+ "contract: 3\nproject: demo\nlanguages: [python]\n"
164
+ "build:\n"
165
+ " feature-sets: >-\n"
166
+ " python -c \"import pathlib; pathlib.Path(r'{{output-file}}').write_text('[]')\"\n"
167
+ " build: >-\n"
168
+ " python -c \"import pathlib; pathlib.Path(r'{{output-file}}').write_text('[]')\"\n",
169
+ encoding="utf-8",
170
+ )
171
+ # Layout behavior is the contract under test; avoid coupling this regression to providers.
172
+ from cpdocs.build import Layout
173
+
174
+ layout = Layout.for_output(project / "build", tmp_directory=tmp_path / "scratch")
175
+ assert layout.root == (project / "build" / "cpdocs").resolve()
176
+ assert layout.work("main") == (tmp_path / "scratch" / "cpdocs" / "work" / "main").resolve()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes