vvz-file-backup 0.1.1__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 (232) hide show
  1. vvz_file_backup-0.1.1/MANIFEST.in +6 -0
  2. vvz_file_backup-0.1.1/PKG-INFO +6 -0
  3. vvz_file_backup-0.1.1/README.md +31 -0
  4. vvz_file_backup-0.1.1/build.sh +126 -0
  5. vvz_file_backup-0.1.1/docs/CATALOG_DIRECTORY.md +50 -0
  6. vvz_file_backup-0.1.1/docs/PIPELINE_STUB_MANIFEST.md +65 -0
  7. vvz_file_backup-0.1.1/docs/STAGE0.md +50 -0
  8. vvz_file_backup-0.1.1/docs/USER_GUIDE.md +101 -0
  9. vvz_file_backup-0.1.1/docs/catalog-directory-validation.json +14 -0
  10. vvz_file_backup-0.1.1/docs/package-api-matrix.json +49235 -0
  11. vvz_file_backup-0.1.1/docs/planner/matrix.md +52 -0
  12. vvz_file_backup-0.1.1/docs/planner/relations.md +90 -0
  13. vvz_file_backup-0.1.1/docs/planner/results.md +277 -0
  14. vvz_file_backup-0.1.1/docs/validation-evidence.json +63 -0
  15. vvz_file_backup-0.1.1/examples/01_backup_lifecycle.py +72 -0
  16. vvz_file_backup-0.1.1/examples/02_catalog_browse.py +51 -0
  17. vvz_file_backup-0.1.1/examples/03_restore_and_preview.py +88 -0
  18. vvz_file_backup-0.1.1/examples/04_verify_and_chain_failure.py +58 -0
  19. vvz_file_backup-0.1.1/examples/05_typed_errors_and_conflicts.py +78 -0
  20. vvz_file_backup-0.1.1/examples/06_catalog_configuration.py +57 -0
  21. vvz_file_backup-0.1.1/examples/07_metadata_and_schemas.py +63 -0
  22. vvz_file_backup-0.1.1/examples/08_help_and_info.py +45 -0
  23. vvz_file_backup-0.1.1/examples/09_thin_cli.py +70 -0
  24. vvz_file_backup-0.1.1/examples/10_offline_installed_restore.py +52 -0
  25. vvz_file_backup-0.1.1/examples/11_recover_catalog.py +60 -0
  26. vvz_file_backup-0.1.1/examples/manifest.json +15 -0
  27. vvz_file_backup-0.1.1/pipeline/__main__.py +2 -0
  28. vvz_file_backup-0.1.1/pipeline/cases.py +334 -0
  29. vvz_file_backup-0.1.1/pipeline/catalog_cases.py +131 -0
  30. vvz_file_backup-0.1.1/pipeline/checks/check_package_backup.py +5 -0
  31. vvz_file_backup-0.1.1/pipeline/checks/check_package_backup_get_schema.py +5 -0
  32. vvz_file_backup-0.1.1/pipeline/checks/check_package_backup_metadata.py +5 -0
  33. vvz_file_backup-0.1.1/pipeline/checks/check_package_build_publication.py +5 -0
  34. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_backup.py +5 -0
  35. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_boundary.py +5 -0
  36. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_help.py +5 -0
  37. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_info.py +5 -0
  38. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_inspect_point.py +5 -0
  39. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_list_files.py +5 -0
  40. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_list_points.py +5 -0
  41. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_recover_catalog.py +5 -0
  42. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_restore.py +5 -0
  43. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_restore_file.py +5 -0
  44. vvz_file_backup-0.1.1/pipeline/checks/check_package_cli_verify.py +5 -0
  45. vvz_file_backup-0.1.1/pipeline/checks/check_package_distribution.py +5 -0
  46. vvz_file_backup-0.1.1/pipeline/checks/check_package_examples.py +4 -0
  47. vvz_file_backup-0.1.1/pipeline/checks/check_package_help.py +5 -0
  48. vvz_file_backup-0.1.1/pipeline/checks/check_package_help_get_schema.py +5 -0
  49. vvz_file_backup-0.1.1/pipeline/checks/check_package_help_metadata.py +5 -0
  50. vvz_file_backup-0.1.1/pipeline/checks/check_package_info.py +5 -0
  51. vvz_file_backup-0.1.1/pipeline/checks/check_package_info_get_schema.py +5 -0
  52. vvz_file_backup-0.1.1/pipeline/checks/check_package_info_metadata.py +5 -0
  53. vvz_file_backup-0.1.1/pipeline/checks/check_package_inspect_point.py +5 -0
  54. vvz_file_backup-0.1.1/pipeline/checks/check_package_inspect_point_get_schema.py +5 -0
  55. vvz_file_backup-0.1.1/pipeline/checks/check_package_inspect_point_metadata.py +5 -0
  56. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_files.py +5 -0
  57. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_files_get_schema.py +5 -0
  58. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_files_metadata.py +5 -0
  59. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_points.py +5 -0
  60. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_points_get_schema.py +5 -0
  61. vvz_file_backup-0.1.1/pipeline/checks/check_package_list_points_metadata.py +5 -0
  62. vvz_file_backup-0.1.1/pipeline/checks/check_package_published_artifact.py +5 -0
  63. vvz_file_backup-0.1.1/pipeline/checks/check_package_recover_catalog.py +5 -0
  64. vvz_file_backup-0.1.1/pipeline/checks/check_package_recover_catalog_get_schema.py +5 -0
  65. vvz_file_backup-0.1.1/pipeline/checks/check_package_recover_catalog_metadata.py +5 -0
  66. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore.py +5 -0
  67. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore_file.py +5 -0
  68. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore_file_get_schema.py +5 -0
  69. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore_file_metadata.py +5 -0
  70. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore_get_schema.py +5 -0
  71. vvz_file_backup-0.1.1/pipeline/checks/check_package_restore_metadata.py +5 -0
  72. vvz_file_backup-0.1.1/pipeline/checks/check_package_verify.py +5 -0
  73. vvz_file_backup-0.1.1/pipeline/checks/check_package_verify_get_schema.py +5 -0
  74. vvz_file_backup-0.1.1/pipeline/checks/check_package_verify_metadata.py +5 -0
  75. vvz_file_backup-0.1.1/pipeline/examples_checks.py +91 -0
  76. vvz_file_backup-0.1.1/pipeline/fixtures.py +4 -0
  77. vvz_file_backup-0.1.1/pipeline/helpers.py +4 -0
  78. vvz_file_backup-0.1.1/pipeline/integration_cases.py +338 -0
  79. vvz_file_backup-0.1.1/pipeline/main.py +2 -0
  80. vvz_file_backup-0.1.1/pipeline/matrix.json +49955 -0
  81. vvz_file_backup-0.1.1/pipeline/packaging_checks.py +444 -0
  82. vvz_file_backup-0.1.1/pipeline/run.py +5 -0
  83. vvz_file_backup-0.1.1/pipeline/runner.py +99 -0
  84. vvz_file_backup-0.1.1/pyproject.toml +27 -0
  85. vvz_file_backup-0.1.1/setup.cfg +4 -0
  86. vvz_file_backup-0.1.1/src/file_backup/__init__.py +60 -0
  87. vvz_file_backup-0.1.1/src/file_backup/_archives.py +100 -0
  88. vvz_file_backup-0.1.1/src/file_backup/_catalog.py +87 -0
  89. vvz_file_backup-0.1.1/src/file_backup/_configuration.py +40 -0
  90. vvz_file_backup-0.1.1/src/file_backup/_namespace.py +16 -0
  91. vvz_file_backup-0.1.1/src/file_backup/_operations.py +356 -0
  92. vvz_file_backup-0.1.1/src/file_backup/_resources.py +7 -0
  93. vvz_file_backup-0.1.1/src/file_backup/_validation.py +82 -0
  94. vvz_file_backup-0.1.1/src/file_backup/api/backup/__init__.py +15 -0
  95. vvz_file_backup-0.1.1/src/file_backup/api/backup/execute/__init__.py +1 -0
  96. vvz_file_backup-0.1.1/src/file_backup/api/backup/execute/implementation.py +12 -0
  97. vvz_file_backup-0.1.1/src/file_backup/api/backup/execute/metadata.json +73 -0
  98. vvz_file_backup-0.1.1/src/file_backup/api/backup/execute/schema.json +50 -0
  99. vvz_file_backup-0.1.1/src/file_backup/api/backup/get_schema/__init__.py +1 -0
  100. vvz_file_backup-0.1.1/src/file_backup/api/backup/get_schema/implementation.py +11 -0
  101. vvz_file_backup-0.1.1/src/file_backup/api/backup/get_schema/metadata.json +53 -0
  102. vvz_file_backup-0.1.1/src/file_backup/api/backup/get_schema/schema.json +6 -0
  103. vvz_file_backup-0.1.1/src/file_backup/api/backup/metadata/__init__.py +1 -0
  104. vvz_file_backup-0.1.1/src/file_backup/api/backup/metadata/implementation.py +11 -0
  105. vvz_file_backup-0.1.1/src/file_backup/api/backup/metadata/metadata.json +53 -0
  106. vvz_file_backup-0.1.1/src/file_backup/api/backup/metadata/schema.json +6 -0
  107. vvz_file_backup-0.1.1/src/file_backup/api/help/__init__.py +15 -0
  108. vvz_file_backup-0.1.1/src/file_backup/api/help/execute/__init__.py +1 -0
  109. vvz_file_backup-0.1.1/src/file_backup/api/help/execute/implementation.py +66 -0
  110. vvz_file_backup-0.1.1/src/file_backup/api/help/execute/metadata.json +34 -0
  111. vvz_file_backup-0.1.1/src/file_backup/api/help/execute/schema.json +23 -0
  112. vvz_file_backup-0.1.1/src/file_backup/api/help/get_schema/__init__.py +1 -0
  113. vvz_file_backup-0.1.1/src/file_backup/api/help/get_schema/implementation.py +15 -0
  114. vvz_file_backup-0.1.1/src/file_backup/api/help/get_schema/metadata.json +20 -0
  115. vvz_file_backup-0.1.1/src/file_backup/api/help/get_schema/schema.json +6 -0
  116. vvz_file_backup-0.1.1/src/file_backup/api/help/metadata/__init__.py +1 -0
  117. vvz_file_backup-0.1.1/src/file_backup/api/help/metadata/implementation.py +15 -0
  118. vvz_file_backup-0.1.1/src/file_backup/api/help/metadata/metadata.json +20 -0
  119. vvz_file_backup-0.1.1/src/file_backup/api/help/metadata/schema.json +6 -0
  120. vvz_file_backup-0.1.1/src/file_backup/api/info/USER_GUIDE.md +101 -0
  121. vvz_file_backup-0.1.1/src/file_backup/api/info/__init__.py +15 -0
  122. vvz_file_backup-0.1.1/src/file_backup/api/info/execute/__init__.py +1 -0
  123. vvz_file_backup-0.1.1/src/file_backup/api/info/execute/implementation.py +79 -0
  124. vvz_file_backup-0.1.1/src/file_backup/api/info/execute/metadata.json +34 -0
  125. vvz_file_backup-0.1.1/src/file_backup/api/info/execute/schema.json +19 -0
  126. vvz_file_backup-0.1.1/src/file_backup/api/info/get_schema/__init__.py +1 -0
  127. vvz_file_backup-0.1.1/src/file_backup/api/info/get_schema/implementation.py +15 -0
  128. vvz_file_backup-0.1.1/src/file_backup/api/info/get_schema/metadata.json +20 -0
  129. vvz_file_backup-0.1.1/src/file_backup/api/info/get_schema/schema.json +6 -0
  130. vvz_file_backup-0.1.1/src/file_backup/api/info/metadata/__init__.py +1 -0
  131. vvz_file_backup-0.1.1/src/file_backup/api/info/metadata/implementation.py +15 -0
  132. vvz_file_backup-0.1.1/src/file_backup/api/info/metadata/metadata.json +20 -0
  133. vvz_file_backup-0.1.1/src/file_backup/api/info/metadata/schema.json +6 -0
  134. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/__init__.py +15 -0
  135. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/execute/__init__.py +1 -0
  136. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/execute/implementation.py +12 -0
  137. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/execute/metadata.json +64 -0
  138. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/execute/schema.json +42 -0
  139. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/get_schema/__init__.py +1 -0
  140. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/get_schema/implementation.py +11 -0
  141. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/get_schema/metadata.json +44 -0
  142. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/get_schema/schema.json +6 -0
  143. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/metadata/__init__.py +1 -0
  144. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/metadata/implementation.py +11 -0
  145. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/metadata/metadata.json +44 -0
  146. vvz_file_backup-0.1.1/src/file_backup/api/inspect_point/metadata/schema.json +6 -0
  147. vvz_file_backup-0.1.1/src/file_backup/api/list_files/__init__.py +15 -0
  148. vvz_file_backup-0.1.1/src/file_backup/api/list_files/execute/__init__.py +1 -0
  149. vvz_file_backup-0.1.1/src/file_backup/api/list_files/execute/implementation.py +12 -0
  150. vvz_file_backup-0.1.1/src/file_backup/api/list_files/execute/metadata.json +64 -0
  151. vvz_file_backup-0.1.1/src/file_backup/api/list_files/execute/schema.json +42 -0
  152. vvz_file_backup-0.1.1/src/file_backup/api/list_files/get_schema/__init__.py +1 -0
  153. vvz_file_backup-0.1.1/src/file_backup/api/list_files/get_schema/implementation.py +11 -0
  154. vvz_file_backup-0.1.1/src/file_backup/api/list_files/get_schema/metadata.json +44 -0
  155. vvz_file_backup-0.1.1/src/file_backup/api/list_files/get_schema/schema.json +6 -0
  156. vvz_file_backup-0.1.1/src/file_backup/api/list_files/metadata/__init__.py +1 -0
  157. vvz_file_backup-0.1.1/src/file_backup/api/list_files/metadata/implementation.py +11 -0
  158. vvz_file_backup-0.1.1/src/file_backup/api/list_files/metadata/metadata.json +44 -0
  159. vvz_file_backup-0.1.1/src/file_backup/api/list_files/metadata/schema.json +6 -0
  160. vvz_file_backup-0.1.1/src/file_backup/api/list_points/__init__.py +15 -0
  161. vvz_file_backup-0.1.1/src/file_backup/api/list_points/execute/__init__.py +1 -0
  162. vvz_file_backup-0.1.1/src/file_backup/api/list_points/execute/implementation.py +12 -0
  163. vvz_file_backup-0.1.1/src/file_backup/api/list_points/execute/metadata.json +55 -0
  164. vvz_file_backup-0.1.1/src/file_backup/api/list_points/execute/schema.json +37 -0
  165. vvz_file_backup-0.1.1/src/file_backup/api/list_points/get_schema/__init__.py +1 -0
  166. vvz_file_backup-0.1.1/src/file_backup/api/list_points/get_schema/implementation.py +11 -0
  167. vvz_file_backup-0.1.1/src/file_backup/api/list_points/get_schema/metadata.json +35 -0
  168. vvz_file_backup-0.1.1/src/file_backup/api/list_points/get_schema/schema.json +6 -0
  169. vvz_file_backup-0.1.1/src/file_backup/api/list_points/metadata/__init__.py +1 -0
  170. vvz_file_backup-0.1.1/src/file_backup/api/list_points/metadata/implementation.py +11 -0
  171. vvz_file_backup-0.1.1/src/file_backup/api/list_points/metadata/metadata.json +35 -0
  172. vvz_file_backup-0.1.1/src/file_backup/api/list_points/metadata/schema.json +6 -0
  173. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/__init__.py +15 -0
  174. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/execute/__init__.py +1 -0
  175. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/execute/implementation.py +12 -0
  176. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/execute/metadata.json +82 -0
  177. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/execute/schema.json +55 -0
  178. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/get_schema/__init__.py +1 -0
  179. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/get_schema/implementation.py +11 -0
  180. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/get_schema/metadata.json +62 -0
  181. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/get_schema/schema.json +6 -0
  182. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/metadata/__init__.py +1 -0
  183. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/metadata/implementation.py +11 -0
  184. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/metadata/metadata.json +62 -0
  185. vvz_file_backup-0.1.1/src/file_backup/api/recover_catalog/metadata/schema.json +6 -0
  186. vvz_file_backup-0.1.1/src/file_backup/api/restore/__init__.py +15 -0
  187. vvz_file_backup-0.1.1/src/file_backup/api/restore/execute/__init__.py +1 -0
  188. vvz_file_backup-0.1.1/src/file_backup/api/restore/execute/implementation.py +12 -0
  189. vvz_file_backup-0.1.1/src/file_backup/api/restore/execute/metadata.json +82 -0
  190. vvz_file_backup-0.1.1/src/file_backup/api/restore/execute/schema.json +55 -0
  191. vvz_file_backup-0.1.1/src/file_backup/api/restore/get_schema/__init__.py +1 -0
  192. vvz_file_backup-0.1.1/src/file_backup/api/restore/get_schema/implementation.py +11 -0
  193. vvz_file_backup-0.1.1/src/file_backup/api/restore/get_schema/metadata.json +62 -0
  194. vvz_file_backup-0.1.1/src/file_backup/api/restore/get_schema/schema.json +6 -0
  195. vvz_file_backup-0.1.1/src/file_backup/api/restore/metadata/__init__.py +1 -0
  196. vvz_file_backup-0.1.1/src/file_backup/api/restore/metadata/implementation.py +11 -0
  197. vvz_file_backup-0.1.1/src/file_backup/api/restore/metadata/metadata.json +62 -0
  198. vvz_file_backup-0.1.1/src/file_backup/api/restore/metadata/schema.json +6 -0
  199. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/__init__.py +15 -0
  200. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/execute/__init__.py +1 -0
  201. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/execute/implementation.py +12 -0
  202. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/execute/metadata.json +100 -0
  203. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/execute/schema.json +68 -0
  204. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/get_schema/__init__.py +1 -0
  205. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/get_schema/implementation.py +11 -0
  206. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/get_schema/metadata.json +80 -0
  207. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/get_schema/schema.json +6 -0
  208. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/metadata/__init__.py +1 -0
  209. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/metadata/implementation.py +11 -0
  210. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/metadata/metadata.json +80 -0
  211. vvz_file_backup-0.1.1/src/file_backup/api/restore_file/metadata/schema.json +6 -0
  212. vvz_file_backup-0.1.1/src/file_backup/api/verify/__init__.py +15 -0
  213. vvz_file_backup-0.1.1/src/file_backup/api/verify/execute/__init__.py +1 -0
  214. vvz_file_backup-0.1.1/src/file_backup/api/verify/execute/implementation.py +12 -0
  215. vvz_file_backup-0.1.1/src/file_backup/api/verify/execute/metadata.json +64 -0
  216. vvz_file_backup-0.1.1/src/file_backup/api/verify/execute/schema.json +42 -0
  217. vvz_file_backup-0.1.1/src/file_backup/api/verify/get_schema/__init__.py +1 -0
  218. vvz_file_backup-0.1.1/src/file_backup/api/verify/get_schema/implementation.py +11 -0
  219. vvz_file_backup-0.1.1/src/file_backup/api/verify/get_schema/metadata.json +44 -0
  220. vvz_file_backup-0.1.1/src/file_backup/api/verify/get_schema/schema.json +6 -0
  221. vvz_file_backup-0.1.1/src/file_backup/api/verify/metadata/__init__.py +1 -0
  222. vvz_file_backup-0.1.1/src/file_backup/api/verify/metadata/implementation.py +11 -0
  223. vvz_file_backup-0.1.1/src/file_backup/api/verify/metadata/metadata.json +44 -0
  224. vvz_file_backup-0.1.1/src/file_backup/api/verify/metadata/schema.json +6 -0
  225. vvz_file_backup-0.1.1/src/file_backup/cli.py +332 -0
  226. vvz_file_backup-0.1.1/src/file_backup/errors.py +100 -0
  227. vvz_file_backup-0.1.1/src/file_backup/types.py +159 -0
  228. vvz_file_backup-0.1.1/src/vvz_file_backup.egg-info/PKG-INFO +6 -0
  229. vvz_file_backup-0.1.1/src/vvz_file_backup.egg-info/SOURCES.txt +230 -0
  230. vvz_file_backup-0.1.1/src/vvz_file_backup.egg-info/dependency_links.txt +1 -0
  231. vvz_file_backup-0.1.1/src/vvz_file_backup.egg-info/entry_points.txt +2 -0
  232. vvz_file_backup-0.1.1/src/vvz_file_backup.egg-info/top_level.txt +1 -0
@@ -0,0 +1,6 @@
1
+ include pyproject.toml README.md build.sh
2
+ recursive-include examples *.py *.json *.md
3
+ recursive-include pipeline *.py *.json
4
+ recursive-include docs *.md *.json *.yaml
5
+ prune pipeline/evidence
6
+ global-exclude __pycache__ *.py[cod]
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: vvz-file-backup
3
+ Version: 0.1.1
4
+ Summary: Independent incremental file backups with verified saved-point restoration
5
+ Author-email: Vasiliy Zdanovskiy <vasilyvz@gmail.com>
6
+ Requires-Python: >=3.11
@@ -0,0 +1,31 @@
1
+ # File Backup package
2
+
3
+ `vvz-file-backup` backs up regular-file trees into immutable full and incremental points, lists and verifies saved data, and restores a whole tree or one selected file. The Python API is the primary interface. The installed `file-backup` command is a thin adapter for shell use.
4
+
5
+ ## Runnable examples
6
+
7
+ Start with the [examples directory](examples/). Each script has a module docstring that explains when to use it, its inputs and filesystem effects, its results, expected errors, and an exact invocation. Every example is standalone: it imports the installed `file_backup` package, uses a private temporary workspace, and can be run from any current directory.
8
+
9
+ | Example | Usage covered |
10
+ | --- | --- |
11
+ | [`01_backup_lifecycle.py`](examples/01_backup_lifecycle.py) | Full and incremental points, unchanged detection, deletions, previews, saved points, and full-base fallback |
12
+ | [`02_catalog_browse.py`](examples/02_catalog_browse.py) | Listing points, inspecting lineage, and listing files |
13
+ | [`03_restore_and_preview.py`](examples/03_restore_and_preview.py) | Full and selective restore, previews, overwrite, and destination conflicts |
14
+ | [`04_verify_and_chain_failure.py`](examples/04_verify_and_chain_failure.py) | Integrity verification and a missing incremental dependency |
15
+ | [`05_typed_errors_and_conflicts.py`](examples/05_typed_errors_and_conflicts.py) | Validation, missing point/file, conflict errors, and safe failure effects |
16
+ | [`06_catalog_configuration.py`](examples/06_catalog_configuration.py) | Explicit catalog directory, config mapping, and default priority |
17
+ | [`07_metadata_and_schemas.py`](examples/07_metadata_and_schemas.py) | Metadata and schema accessors for all public operation classes |
18
+ | [`08_help_and_info.py`](examples/08_help_and_info.py) | Metadata-driven help and installed guide sections |
19
+ | [`09_thin_cli.py`](examples/09_thin_cli.py) | JSON command-line results and typed CLI errors |
20
+ | [`10_offline_installed_restore.py`](examples/10_offline_installed_restore.py) | Installed-package import and offline archive/restore flow |
21
+ | [`11_recover_catalog.py`](examples/11_recover_catalog.py) | Preview and recover a validated catalog copy |
22
+
23
+ Run an example from any directory after installing the package:
24
+
25
+ ```sh
26
+ python /path/to/file-backup/examples/01_backup_lifecycle.py
27
+ ```
28
+
29
+ The machine-readable [`manifest.json`](examples/manifest.json) maps each script to its public capability coverage. The package pipeline executes the listed scripts independently against a clean installed build. Distribution packaging must include this examples directory and manifest so the same guide remains available after installation.
30
+
31
+ The normative method, parameter, result, relationship, and side-effect contract is in [`docs/package-api-matrix.json`](docs/package-api-matrix.json). Use it for exhaustive integration details; start with the runnable examples for practical usage.
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # Never trace credentials inherited from the caller, including with bash -x.
4
+ set +x
5
+
6
+ PACKAGE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ PYTHON="${FILE_BACKUP_PYTHON:-python}"
8
+ cd "$PACKAGE_ROOT"
9
+
10
+ error() { echo "ERROR: $*" >&2; exit 1; }
11
+ info() { echo "INFO: $*"; }
12
+
13
+ [[ $# -eq 0 ]] || error "This command accepts no arguments; set FILE_BACKUP_VERSION for an explicit package version"
14
+ [[ ! -L "$PACKAGE_ROOT/pyproject.toml" && -f "$PACKAGE_ROOT/pyproject.toml" ]] \
15
+ || error "Package pyproject.toml must be a regular file"
16
+ command -v "$PYTHON" >/dev/null 2>&1 || error "Python is required: $PYTHON"
17
+
18
+ VERSION="$($PYTHON - "$PACKAGE_ROOT/pyproject.toml" "${FILE_BACKUP_VERSION:-}" <<'PY'
19
+ from pathlib import Path
20
+ import re
21
+ import sys
22
+ import tomllib
23
+ from packaging.version import InvalidVersion, Version
24
+
25
+ path = Path(sys.argv[1])
26
+ requested_text = sys.argv[2]
27
+ project = tomllib.loads(path.read_text(encoding="utf-8"))["project"]
28
+ if project.get("name") != "vvz-file-backup":
29
+ raise SystemExit("Package distribution name must be vvz-file-backup")
30
+ current_text = project["version"]
31
+ try:
32
+ current = Version(current_text)
33
+ except InvalidVersion:
34
+ raise SystemExit(f"Current package version is not valid PEP 440: {current_text}")
35
+
36
+ if requested_text:
37
+ try:
38
+ requested = Version(requested_text)
39
+ except InvalidVersion:
40
+ raise SystemExit(f"Requested package version is not valid PEP 440: {requested_text}")
41
+ if requested <= current:
42
+ raise SystemExit(
43
+ f"Requested package version {requested_text} must be greater than current version {current_text}"
44
+ )
45
+ target_text = requested_text
46
+ else:
47
+ release = list(current.release)
48
+ if not release:
49
+ raise SystemExit(f"Current package version has no release numbers: {current_text}")
50
+ release[-1] += 1
51
+ epoch = f"{current.epoch}!" if current.epoch else ""
52
+ target_text = epoch + ".".join(str(number) for number in release)
53
+ print(target_text)
54
+ PY
55
+ )" || error "Unable to select the file-backup package version"
56
+
57
+ # Persist the selected independent package version before building so the
58
+ # sdist and wheel metadata agree with the next root release state.
59
+ "$PYTHON" - "$PACKAGE_ROOT/pyproject.toml" "$VERSION" <<'PY'
60
+ import json
61
+ from pathlib import Path
62
+ import re
63
+ import sys
64
+ import tomllib
65
+
66
+ path = Path(sys.argv[1])
67
+ text = path.read_text(encoding="utf-8")
68
+ project = tomllib.loads(text)["project"]
69
+ updated, count = re.subn(
70
+ r'(?m)^(version\s*=\s*)"[^\"]+"$',
71
+ lambda match: f'{match.group(1)}"{sys.argv[2]}"',
72
+ text,
73
+ count=1,
74
+ )
75
+ if count != 1 or updated == text and project["version"] != sys.argv[2]:
76
+ raise SystemExit("Unable to update the package version in pyproject.toml")
77
+
78
+ metadata_paths = sorted((path.parent / "src/file_backup/api").rglob("metadata.json"))
79
+ if len(metadata_paths) != 30:
80
+ raise SystemExit(f"Expected 30 API metadata files, found {len(metadata_paths)}")
81
+ metadata_updates = []
82
+ for metadata_path in metadata_paths:
83
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
84
+ if not isinstance(metadata, dict) or "version" not in metadata:
85
+ raise SystemExit(f"API metadata has no version field: {metadata_path}")
86
+ metadata["version"] = sys.argv[2]
87
+ metadata_updates.append(
88
+ (metadata_path, json.dumps(metadata, ensure_ascii=False, indent=2) + "\n")
89
+ )
90
+
91
+ path.write_text(updated, encoding="utf-8")
92
+ for metadata_path, metadata_text in metadata_updates:
93
+ metadata_path.write_text(metadata_text, encoding="utf-8")
94
+ PY
95
+
96
+ if [[ -n "${PYPI_API_TOKEN:-}" ]]; then
97
+ export TWINE_USERNAME="__token__"
98
+ export TWINE_PASSWORD="$PYPI_API_TOKEN"
99
+ elif [[ -z "${TWINE_USERNAME:-}" || -z "${TWINE_PASSWORD:-}" ]]; then
100
+ [[ -f "${HOME}/.pypirc" ]] \
101
+ || error "PyPI credentials are required: PYPI_API_TOKEN, TWINE_USERNAME/TWINE_PASSWORD, or ~/.pypirc"
102
+ fi
103
+
104
+ BUILD_DIR="$(mktemp -d "${TMPDIR:-/tmp}/vvz-file-backup-dist.XXXXXX")"
105
+ cleanup() { rm -rf -- "$BUILD_DIR"; }
106
+ trap cleanup EXIT
107
+
108
+ info "Building vvz-file-backup $VERSION"
109
+ "$PYTHON" -m build --sdist --wheel --outdir "$BUILD_DIR" "$PACKAGE_ROOT"
110
+
111
+ WHEEL="vvz_file_backup-${VERSION}-py3-none-any.whl"
112
+ SDIST="vvz_file_backup-${VERSION}.tar.gz"
113
+ [[ -f "$BUILD_DIR/$WHEEL" && ! -L "$BUILD_DIR/$WHEEL" ]] \
114
+ || error "Expected wheel was not built: $WHEEL"
115
+ [[ -f "$BUILD_DIR/$SDIST" && ! -L "$BUILD_DIR/$SDIST" ]] \
116
+ || error "Expected sdist was not built: $SDIST"
117
+ shopt -s nullglob
118
+ ARTIFACTS=("$BUILD_DIR"/*)
119
+ [[ ${#ARTIFACTS[@]} -eq 2 ]] || error "Build produced unexpected artifacts for vvz-file-backup $VERSION"
120
+
121
+ "$PYTHON" -m twine check "${ARTIFACTS[@]}"
122
+ info "Running final package examples check"
123
+ "$PYTHON" "$PACKAGE_ROOT/pipeline/run.py" package_examples
124
+ info "Publishing vvz-file-backup $VERSION to PyPI"
125
+ "$PYTHON" -m twine upload --non-interactive \
126
+ --repository-url https://upload.pypi.org/legacy/ "${ARTIFACTS[@]}"
@@ -0,0 +1,50 @@
1
+ # Configurable SQLite catalog directory
2
+
3
+ The eight repository operations (backup, list_points, inspect_point, list_files,
4
+ restore, restore_file, verify, recover_catalog) accept two keyword-only arguments:
5
+ `catalog_directory: str | None = None` and
6
+ `config: Mapping[str, object] | None = None`.
7
+
8
+ Resolution order is an explicit non-None argument, `config['catalog_directory']`,
9
+ then the exported string constant `file_backup.DEFAULT_CATALOG_DIRECTORY = '.'`.
10
+ The eight CLI commands accept `--catalog-directory DIR` and `--config JSONFILE`
11
+ with the same priority. Config-file paths resolve from the process working
12
+ directory; catalog paths resolve from the repository. No environment or ambient
13
+ configuration source is introduced.
14
+
15
+ Omitted/None config means an empty mapping. An empty mapping selects the default.
16
+ Only the key `catalog_directory` is accepted; a present value must be a nonempty,
17
+ NUL-free string. A present null, unknown key, wrong type, empty string or NUL is
18
+ ArgumentError even when an explicit directory wins. The caller's mapping is not
19
+ mutated. CLI JSON must be a UTF-8 object; missing/unreadable/malformed config is
20
+ ArgumentError (exit 2, empty stdout, typed error on stderr).
21
+
22
+ Relative catalog directory paths, including `..`, normalize against repository;
23
+ absolute directories are accepted. Symlink components and an existing regular
24
+ file in place of a directory are ArgumentError. The selected database is
25
+ `<resolved-directory>/catalog.sqlite3`; SQLite temporary sidecars and lock files
26
+ belong there. Archives remain at `<repository>/archives`. The default therefore
27
+ keeps the catalog on the backup repository's volume. Reading and dry-run calls
28
+ create no database, directory, archive or checkpoint.
29
+
30
+ No implicit migration, fallback or active database replacement occurs. A missing
31
+ selected database while archives exist raises CatalogError, including when a
32
+ valid catalog remains at the old/default location. Recovery is the exception:
33
+ recover_catalog accepts an absent active catalog with a valid supplied copy and
34
+ writes only its new destination. An empty repository may be
35
+ initialized at the selected directory. Selecting an already-placed valid copy
36
+ for the same archive repository is supported; existing catalog/archive bytes
37
+ remain unchanged. recover_catalog still writes its new destination only and does
38
+ not install it. Backup's source and selected catalog directory must be disjoint;
39
+ restore destinations must be outside the selected catalog directory. Recovery's
40
+ destination cannot be the selected active database.
41
+
42
+ The complete machine contract is `package-api-matrix.json`:
43
+ `catalog_directory_contract`, updated input cells/schema/signatures and
44
+ `catalog_directory_delta.new_case_ids`. All 40 original rows, 472 original cases,
45
+ 14 relation cases and four packaging scenarios are retained. 318 focused cases
46
+ are appended, for 790 total. Existing service rows are separate and preserved.
47
+ The native planner tables remain historical projections; the full JSON annex
48
+ governs this TODO-only change. No PLAN/HRS/MRS/G/T/A/freeze operation is required
49
+ or performed under the user's explicit boundary. Runtime acceptance remains the
50
+ tester's matrix/check RED followed by the same mapped GREEN and full pipeline.
@@ -0,0 +1,65 @@
1
+ # File Backup Pipeline Stub Manifest
2
+
3
+ Status: **NOT_IMPLEMENTED**. These declarations do not execute checks and provide no product GREEN.
4
+
5
+ ## Source and scope
6
+
7
+ - Source matrix: `docs/package-api-matrix.json` (mutable stage-0 design).
8
+ - Mapping totals: 40 rows, 472 cases, 14 relation cases, 4 packaging scenarios, 490 mappings.
9
+ - Declared checks: 44; each check function raises `NotImplementedError`.
10
+ - Matrix mapping: `pipeline/matrix.json`; every mapping retains its scenario ID, future inputs and source expected result/error/side-effect contract where present. Packaging scenarios whose source defines assertions only are marked as lacking explicit error/side-effect contracts.
11
+ - Runner, CLI entrypoint, fixtures and helpers are declarations that raise `NotImplementedError`; no parser, dispatch, coverage algorithm or test algorithm is present.
12
+
13
+ ## Check declarations
14
+
15
+ - `package_backup` -> `pipeline/checks/check_package_backup.py`; `check_package_backup() -> None`; **NOT_IMPLEMENTED**.
16
+ - `package_backup_get_schema` -> `pipeline/checks/check_package_backup_get_schema.py`; `check_package_backup_get_schema() -> None`; **NOT_IMPLEMENTED**.
17
+ - `package_backup_metadata` -> `pipeline/checks/check_package_backup_metadata.py`; `check_package_backup_metadata() -> None`; **NOT_IMPLEMENTED**.
18
+ - `package_build_publication` -> `pipeline/checks/check_package_build_publication.py`; `check_package_build_publication() -> None`; **NOT_IMPLEMENTED**.
19
+ - `package_cli_backup` -> `pipeline/checks/check_package_cli_backup.py`; `check_package_cli_backup() -> None`; **NOT_IMPLEMENTED**.
20
+ - `package_cli_boundary` -> `pipeline/checks/check_package_cli_boundary.py`; `check_package_cli_boundary() -> None`; **NOT_IMPLEMENTED**.
21
+ - `package_cli_help` -> `pipeline/checks/check_package_cli_help.py`; `check_package_cli_help() -> None`; **NOT_IMPLEMENTED**.
22
+ - `package_cli_info` -> `pipeline/checks/check_package_cli_info.py`; `check_package_cli_info() -> None`; **NOT_IMPLEMENTED**.
23
+ - `package_cli_inspect_point` -> `pipeline/checks/check_package_cli_inspect_point.py`; `check_package_cli_inspect_point() -> None`; **NOT_IMPLEMENTED**.
24
+ - `package_cli_list_files` -> `pipeline/checks/check_package_cli_list_files.py`; `check_package_cli_list_files() -> None`; **NOT_IMPLEMENTED**.
25
+ - `package_cli_list_points` -> `pipeline/checks/check_package_cli_list_points.py`; `check_package_cli_list_points() -> None`; **NOT_IMPLEMENTED**.
26
+ - `package_cli_recover_catalog` -> `pipeline/checks/check_package_cli_recover_catalog.py`; `check_package_cli_recover_catalog() -> None`; **NOT_IMPLEMENTED**.
27
+ - `package_cli_restore` -> `pipeline/checks/check_package_cli_restore.py`; `check_package_cli_restore() -> None`; **NOT_IMPLEMENTED**.
28
+ - `package_cli_restore_file` -> `pipeline/checks/check_package_cli_restore_file.py`; `check_package_cli_restore_file() -> None`; **NOT_IMPLEMENTED**.
29
+ - `package_cli_verify` -> `pipeline/checks/check_package_cli_verify.py`; `check_package_cli_verify() -> None`; **NOT_IMPLEMENTED**.
30
+ - `package_distribution` -> `pipeline/checks/check_package_distribution.py`; `check_package_distribution() -> None`; **NOT_IMPLEMENTED**.
31
+ - `package_help` -> `pipeline/checks/check_package_help.py`; `check_package_help() -> None`; **NOT_IMPLEMENTED**.
32
+ - `package_help_get_schema` -> `pipeline/checks/check_package_help_get_schema.py`; `check_package_help_get_schema() -> None`; **NOT_IMPLEMENTED**.
33
+ - `package_help_metadata` -> `pipeline/checks/check_package_help_metadata.py`; `check_package_help_metadata() -> None`; **NOT_IMPLEMENTED**.
34
+ - `package_info` -> `pipeline/checks/check_package_info.py`; `check_package_info() -> None`; **NOT_IMPLEMENTED**.
35
+ - `package_info_get_schema` -> `pipeline/checks/check_package_info_get_schema.py`; `check_package_info_get_schema() -> None`; **NOT_IMPLEMENTED**.
36
+ - `package_info_metadata` -> `pipeline/checks/check_package_info_metadata.py`; `check_package_info_metadata() -> None`; **NOT_IMPLEMENTED**.
37
+ - `package_inspect_point` -> `pipeline/checks/check_package_inspect_point.py`; `check_package_inspect_point() -> None`; **NOT_IMPLEMENTED**.
38
+ - `package_inspect_point_get_schema` -> `pipeline/checks/check_package_inspect_point_get_schema.py`; `check_package_inspect_point_get_schema() -> None`; **NOT_IMPLEMENTED**.
39
+ - `package_inspect_point_metadata` -> `pipeline/checks/check_package_inspect_point_metadata.py`; `check_package_inspect_point_metadata() -> None`; **NOT_IMPLEMENTED**.
40
+ - `package_list_files` -> `pipeline/checks/check_package_list_files.py`; `check_package_list_files() -> None`; **NOT_IMPLEMENTED**.
41
+ - `package_list_files_get_schema` -> `pipeline/checks/check_package_list_files_get_schema.py`; `check_package_list_files_get_schema() -> None`; **NOT_IMPLEMENTED**.
42
+ - `package_list_files_metadata` -> `pipeline/checks/check_package_list_files_metadata.py`; `check_package_list_files_metadata() -> None`; **NOT_IMPLEMENTED**.
43
+ - `package_list_points` -> `pipeline/checks/check_package_list_points.py`; `check_package_list_points() -> None`; **NOT_IMPLEMENTED**.
44
+ - `package_list_points_get_schema` -> `pipeline/checks/check_package_list_points_get_schema.py`; `check_package_list_points_get_schema() -> None`; **NOT_IMPLEMENTED**.
45
+ - `package_list_points_metadata` -> `pipeline/checks/check_package_list_points_metadata.py`; `check_package_list_points_metadata() -> None`; **NOT_IMPLEMENTED**.
46
+ - `package_published_artifact` -> `pipeline/checks/check_package_published_artifact.py`; `check_package_published_artifact() -> None`; **NOT_IMPLEMENTED**.
47
+ - `package_recover_catalog` -> `pipeline/checks/check_package_recover_catalog.py`; `check_package_recover_catalog() -> None`; **NOT_IMPLEMENTED**.
48
+ - `package_recover_catalog_get_schema` -> `pipeline/checks/check_package_recover_catalog_get_schema.py`; `check_package_recover_catalog_get_schema() -> None`; **NOT_IMPLEMENTED**.
49
+ - `package_recover_catalog_metadata` -> `pipeline/checks/check_package_recover_catalog_metadata.py`; `check_package_recover_catalog_metadata() -> None`; **NOT_IMPLEMENTED**.
50
+ - `package_restore` -> `pipeline/checks/check_package_restore.py`; `check_package_restore() -> None`; **NOT_IMPLEMENTED**.
51
+ - `package_restore_file` -> `pipeline/checks/check_package_restore_file.py`; `check_package_restore_file() -> None`; **NOT_IMPLEMENTED**.
52
+ - `package_restore_file_get_schema` -> `pipeline/checks/check_package_restore_file_get_schema.py`; `check_package_restore_file_get_schema() -> None`; **NOT_IMPLEMENTED**.
53
+ - `package_restore_file_metadata` -> `pipeline/checks/check_package_restore_file_metadata.py`; `check_package_restore_file_metadata() -> None`; **NOT_IMPLEMENTED**.
54
+ - `package_restore_get_schema` -> `pipeline/checks/check_package_restore_get_schema.py`; `check_package_restore_get_schema() -> None`; **NOT_IMPLEMENTED**.
55
+ - `package_restore_metadata` -> `pipeline/checks/check_package_restore_metadata.py`; `check_package_restore_metadata() -> None`; **NOT_IMPLEMENTED**.
56
+ - `package_verify` -> `pipeline/checks/check_package_verify.py`; `check_package_verify() -> None`; **NOT_IMPLEMENTED**.
57
+ - `package_verify_get_schema` -> `pipeline/checks/check_package_verify_get_schema.py`; `check_package_verify_get_schema() -> None`; **NOT_IMPLEMENTED**.
58
+ - `package_verify_metadata` -> `pipeline/checks/check_package_verify_metadata.py`; `check_package_verify_metadata() -> None`; **NOT_IMPLEMENTED**.
59
+
60
+ ## Boundaries
61
+
62
+ - No `pipeline` command, test, build, install, publication, deployment, push or synchronization was run.
63
+ - No product API, existing package asset, root build script or service pipeline was changed.
64
+ - No PLAN/HRS/MRS/G/T/A or cascade artifact was read or changed.
65
+ - All check bodies explicitly raise `NotImplementedError`; the mapping status is `NOT_IMPLEMENTED`.
@@ -0,0 +1,50 @@
1
+ # Package matrix documentary handoff
2
+
3
+ The current scope is TODO-only by explicit user instruction. Do not create, read,
4
+ mutate, import, freeze or validate PLAN/HRS/MRS/G/T/A artifacts for this task.
5
+ This document supersedes the original stage-0 candidate/skeleton handoff.
6
+
7
+ The full authority is package-api-matrix.json, retained as backup_package_stage0
8
+ in project matrix TODO 368a1d2b-5d42-419a-b50b-9f4f8e6e7f81. Project identity is
9
+ ff997eab-d809-4cb9-b805-9dff4df60c6d. Root TODO is
10
+ 55bc5124-9708-46c3-b56c-fbc29ea239b1; execution map is
11
+ c052cd96-0967-4842-8176-b598eab7354a. The separate 45 service rows are preserved.
12
+ The examples requirement is root child 2ed43027-2943-4e29-a17c-bb01f1f27e34.
13
+
14
+ The annex contains 40 call rows (30 Python methods, 10 CLI commands), 790 cases,
15
+ 8 parameter relations with 14 original relation cases, and 5 packaging scenarios:
16
+ 790 + 14 + 5 = 809 required executable mappings. The 318 catalog/config cases
17
+ supplement all 472 original cases. PKG05 supplements the four original packaging
18
+ scenarios. No original focused case, result assertion or server row is waived.
19
+
20
+ The three planner/*.md files are documentary native-dialect projections. They
21
+ retain required Russian headers/grammar and reserved {fb01} source tokens while
22
+ their explanatory prose is English. They describe 40 rows, 76 relation entries
23
+ and 262 shallow result cases. API config projects its JSON-object subset and
24
+ catalog_directory its non-null string subset. Full Mapping/null/omission, config
25
+ key validation, path semantics, typed errors, dynamic results, chains and file
26
+ effects require the full annex. No runtime import/lint verdict is claimed.
27
+
28
+ Catalog priority is explicit API/CLI > config > DEFAULT_CATALOG_DIRECTORY='.'.
29
+ Default catalog.sqlite3 is on the repository volume. See CATALOG_DIRECTORY.md
30
+ and the annex for validation, no-silent-migration and recovery exceptions.
31
+
32
+ The tester owns executable matrix/checks and runtime evidence. Canonical
33
+ examples acceptance is `python file-backup/pipeline/run.py package_examples`.
34
+ The complete `python file-backup/pipeline/run.py --all` runs every other check
35
+ first and package_examples LAST as its final stage. All examples must execute
36
+ adequately; expected errors are caught and asserted; no skip/XFAIL. English
37
+ module docstrings explain purpose, when/why, invocation, prerequisites, files,
38
+ results, effects and errors. Documentation in examples and product code is
39
+ English. build.sh must require successful current-candidate examples BEFORE
40
+ twine upload; any failure is nonzero and blocks publication. Candidate example
41
+ acceptance never depends on a prior publication.
42
+
43
+ This update verifies documentary consistency only. It does not claim a current
44
+ runtime pipeline GREEN, installed-package success or publication. Reuse the
45
+ separate tester/build owner's exact evidence for those states; do not rerun them
46
+ merely because these projections changed.
47
+
48
+ Server obligations remain separate: latest-only document export, an hourly
49
+ worker, a separately mounted backup volume, server API/matrix checks and deployed
50
+ integration acceptance. The package matrix does not replace the server matrix.
@@ -0,0 +1,101 @@
1
+ # File Backup User Guide
2
+
3
+ ## Contents
4
+
5
+ - [Overview](#overview) - `file-backup://info/overview`
6
+ - [Backup](#backup) - `file-backup://info/backup`
7
+ - [Restore](#restore) - `file-backup://info/restore`
8
+ - [Catalog](#catalog) - `file-backup://info/catalog`
9
+ - [Errors](#errors) - `file-backup://info/errors`
10
+ - [Release](#release) - `file-backup://info/release`
11
+
12
+ ## Overview
13
+
14
+ File Backup is a standalone Python package for saving completed filesystem slices and restoring
15
+ them later. Its Python API is available from `file_backup`; its command-line program is
16
+ `file-backup`. Both interfaces use the same operation methods and result contracts.
17
+
18
+ The package stores its catalog and archives under the repository directory supplied to an
19
+ operation. It reads regular files from the source tree and does not preserve ownership, modes,
20
+ timestamps, symbolic links, or empty directories. Keep the source unchanged for the duration of a
21
+ backup call.
22
+
23
+ Use `file-backup help` for command and parameter guidance, or `file-backup info` to print this
24
+ guide's table of contents. The Python equivalents are `Help.execute()` and `Info.execute()`.
25
+
26
+ ## Backup
27
+
28
+ Call `Backup.execute(repository, source)` or `file-backup backup --repository PATH --source PATH`
29
+ to save a completed source tree. The first saved point is full. Later calls save additions,
30
+ changes, and deletion tombstones relative to the previous successful point. A byte-for-byte
31
+ unchanged source creates no archive or saved point. If the full archive needed to continue a chain
32
+ is missing, the next successful backup starts a new full chain.
33
+
34
+ `dry_run=True` or `--dry-run` returns a preview without creating or changing the catalog, archive,
35
+ or checkpoint. The result identifies whether the operation would create a full point, an
36
+ incremental point, or no point.
37
+
38
+ ## Restore
39
+
40
+ Use `Restore.execute(repository, point, destination)` to restore one exact saved point. The
41
+ destination must be absent or empty. The package checks the complete required archive chain and
42
+ content digests before publishing restored files. A missing or corrupt dependency fails the
43
+ operation; it does not return a partial restore or substitute a nearby point.
44
+
45
+ Use `RestoreFile.execute(repository, point, path, destination)` to restore one live relative path.
46
+ The destination file is not replaced unless `overwrite=True` is supplied. A file deleted at the
47
+ selected point is unavailable at that point, even if an older point contains it. Both restore
48
+ operations support a no-write `dry_run` preview.
49
+
50
+ The CLI forms are `file-backup restore --repository PATH --point UUID --destination PATH` and
51
+ `file-backup restore-file --repository PATH --point UUID --path RELATIVE_PATH --destination PATH`.
52
+
53
+ ## Catalog
54
+
55
+ `ListPoints.execute(repository)` lists committed saved points in completion order. Use
56
+ `InspectPoint.execute(repository, point)` for one point's identity and chain, and
57
+ `ListFiles.execute(repository, point)` for its live files. `Verify.execute(repository, point)`
58
+ checks the catalog bindings, archive chain, manifest, and referenced file contents.
59
+
60
+ All eight repository operations accept the keyword-only `catalog_directory` and `config`
61
+ arguments. The selected SQLite file is `catalog.sqlite3` under the selected directory; archives
62
+ remain under `<repository>/archives`. The default is the repository directory itself, exposed as
63
+ `file_backup.DEFAULT_CATALOG_DIRECTORY == "."`. Relative catalog directory values, including
64
+ `..`, resolve from the repository. An absolute catalog directory is also accepted.
65
+
66
+ Selection priority is explicit `catalog_directory`, then `config["catalog_directory"]`, then the
67
+ default constant. A `None` explicit value means unspecified. `config` may be omitted or `None`;
68
+ otherwise it must contain only the nonempty, NUL-free string key `catalog_directory`. Config is
69
+ validated even when an explicit directory takes priority. No environment or ambient config is
70
+ read. The CLI forms are `--catalog-directory DIR` and `--config JSONFILE`; the JSON file path is
71
+ relative to the process working directory, and its UTF-8 JSON object is decoded before the API
72
+ call.
73
+
74
+ The package does not migrate, copy, or fall back to another catalog. If the selected catalog is
75
+ missing while archives exist, the operation fails even when another catalog file is present.
76
+ Read-only operations and dry runs create no catalog directory or database.
77
+
78
+ `RecoverCatalog.execute(repository, destination, catalog_copy)` validates a caller-supplied
79
+ consistent SQLite backup against the repository archives and writes a validated copy to a new
80
+ destination. It does not infer points from loose archive files and does not replace the active
81
+ catalog. Switching an installation to a recovered catalog is a separate offline administrative
82
+ operation.
83
+
84
+ ## Errors
85
+
86
+ Operations raise typed `FileBackupError` subclasses. Each error has a stable `code`, a readable
87
+ `message`, and a `context` mapping with operation-specific fields. Argument errors identify the
88
+ parameter and violation. Missing points, files, archives, corrupt content, broken chains, I/O
89
+ failures, catalog failures, and conflicts have distinct error types.
90
+
91
+ The CLI catches package errors at its boundary. Argument, command-selection, and information
92
+ section-selection errors exit with status 2. Other package errors exit with status 1. Errors are
93
+ written to standard error with their stable code and context; standard output remains empty.
94
+
95
+ ## Release
96
+
97
+ The `vvz-file-backup` distribution contains the importable `file_backup` package, its JSON schema
98
+ and metadata resources, and the installed guide used by `Info.execute()`. It is designed to build
99
+ and install independently of doc-store and adapter packages. Use the package's own build and
100
+ release instructions when preparing a distribution; do not copy credentials into command output
101
+ or logs.
@@ -0,0 +1,14 @@
1
+ {
2
+ "status": "GREEN documentary only; runtime acceptance pending",
3
+ "rule": "CFG-CONTRACT immutable completion criterion",
4
+ "command": "python tmp/validate_catalog_matrix.py",
5
+ "exit_code": 0,
6
+ "matrix_sha256": "9bda0048146ac20520157f2a4cb98d47f3d306eae53d1fb9f059685125dd780d",
7
+ "rows": 40,
8
+ "cases": 790,
9
+ "new_cases": 318,
10
+ "original_cases_preserved": 472,
11
+ "original_result_contracts_preserved": 472,
12
+ "original_relation_cases_preserved": 14,
13
+ "original_packaging_scenarios_preserved": 4
14
+ }