cfengine 0.16.3__tar.gz → 0.16.4__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 (157) hide show
  1. {cfengine-0.16.3 → cfengine-0.16.4}/PKG-INFO +19 -3
  2. {cfengine-0.16.3 → cfengine-0.16.4}/README.md +18 -2
  3. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/PKG-INFO +19 -3
  4. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/commands.py +3 -74
  5. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/dev.py +7 -5
  6. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/docs.py +19 -12
  7. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/format.py +80 -1
  8. {cfengine-0.16.3 → cfengine-0.16.4}/uv.lock +9 -9
  9. {cfengine-0.16.3 → cfengine-0.16.4}/.github/dependabot.yml +0 -0
  10. {cfengine-0.16.3 → cfengine-0.16.4}/.github/workflows/lint-policy-in-other-repos.yml +0 -0
  11. {cfengine-0.16.3 → cfengine-0.16.4}/.github/workflows/make-check.yml +0 -0
  12. {cfengine-0.16.3 → cfengine-0.16.4}/.github/workflows/pypi-publish.yml +0 -0
  13. {cfengine-0.16.3 → cfengine-0.16.4}/.github/workflows/stale.yml +0 -0
  14. {cfengine-0.16.3 → cfengine-0.16.4}/.github/workflows/update-syntax-description.yml +0 -0
  15. {cfengine-0.16.3 → cfengine-0.16.4}/.gitignore +0 -0
  16. {cfengine-0.16.3 → cfengine-0.16.4}/.python-version +0 -0
  17. {cfengine-0.16.3 → cfengine-0.16.4}/CLAUDE.md +0 -0
  18. {cfengine-0.16.3 → cfengine-0.16.4}/HACKING.md +0 -0
  19. {cfengine-0.16.3 → cfengine-0.16.4}/LICENSE +0 -0
  20. {cfengine-0.16.3 → cfengine-0.16.4}/Makefile +0 -0
  21. {cfengine-0.16.3 → cfengine-0.16.4}/ci/01-install.sh +0 -0
  22. {cfengine-0.16.3 → cfengine-0.16.4}/ci/02-safe-tests.sh +0 -0
  23. {cfengine-0.16.3 → cfengine-0.16.4}/ci/03-unsafe-tests.sh +0 -0
  24. {cfengine-0.16.3 → cfengine-0.16.4}/pyproject.toml +0 -0
  25. {cfengine-0.16.3 → cfengine-0.16.4}/setup.cfg +0 -0
  26. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/SOURCES.txt +0 -0
  27. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/dependency_links.txt +0 -0
  28. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/entry_points.txt +0 -0
  29. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/requires.txt +0 -0
  30. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine.egg-info/top_level.txt +0 -0
  31. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/__init__.py +0 -0
  32. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/__main__.py +0 -0
  33. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/changelog.py +0 -0
  34. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/deptool-README.md +0 -0
  35. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/deptool.py +0 -0
  36. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/lint.py +0 -0
  37. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/lint_csv.py +0 -0
  38. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/lint_yml.py +0 -0
  39. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/main.py +0 -0
  40. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/__init__.py +0 -0
  41. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/analyze.py +0 -0
  42. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/check_download_matches_git.py +0 -0
  43. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/download.py +0 -0
  44. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/generate_git_tags.py +0 -0
  45. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/generate_release_information.py +0 -0
  46. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/generate_vcf_download.py +0 -0
  47. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/masterfiles/generate_vcf_git_checkout.py +0 -0
  48. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/paths.py +0 -0
  49. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/profile.py +0 -0
  50. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/shell.py +0 -0
  51. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/syntax-description.json +0 -0
  52. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/syntax_tree.py +0 -0
  53. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/up.py +0 -0
  54. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/utils.py +0 -0
  55. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/validate.py +0 -0
  56. {cfengine-0.16.3 → cfengine-0.16.4}/src/cfengine_cli/version.py +0 -0
  57. {cfengine-0.16.3 → cfengine-0.16.4}/tests/README.md +0 -0
  58. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/001_hello_world.expected.cf +0 -0
  59. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/001_hello_world.input.cf +0 -0
  60. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/002_basics.expected.cf +0 -0
  61. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/002_basics.input.cf +0 -0
  62. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/003_wrapping.expected.cf +0 -0
  63. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/003_wrapping.input.cf +0 -0
  64. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/004_comments.expected.cf +0 -0
  65. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/004_comments.input.cf +0 -0
  66. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/005_bundle_comments.expected.cf +0 -0
  67. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/005_bundle_comments.input.cf +0 -0
  68. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/006_remove_empty_comments.expected.cf +0 -0
  69. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/006_remove_empty_comments.input.cf +0 -0
  70. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/007_class_guarded_empty_lines.expected.cf +0 -0
  71. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/007_class_guarded_empty_lines.input.cf +0 -0
  72. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/008_long_string.expected.cf +0 -0
  73. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/008_long_string.input.cf +0 -0
  74. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/009_single_line.expected.cf +0 -0
  75. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/009_single_line.input.cf +0 -0
  76. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/010_stakeholder.expected.cf +0 -0
  77. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/010_stakeholder.input.cf +0 -0
  78. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/011_macros.expected.cf +0 -0
  79. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/011_macros.input.cf +0 -0
  80. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/011_promises.expected.cf +0 -0
  81. {cfengine-0.16.3 → cfengine-0.16.4}/tests/format/011_promises.input.cf +0 -0
  82. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/001_hello_world.cf +0 -0
  83. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/002_deprecations.expected.txt +0 -0
  84. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/002_deprecations.x.cf +0 -0
  85. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/003_name_lowercase.cf +0 -0
  86. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/003_name_lowercase.expected.txt +0 -0
  87. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/003_name_lowercase.x.cf +0 -0
  88. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/004_block_type.cf +0 -0
  89. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/004_block_type.expected.txt +0 -0
  90. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/004_block_type.x.cf +0 -0
  91. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/005_syntax_error.cf +0 -0
  92. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/005_syntax_error.expected.txt +0 -0
  93. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/005_syntax_error.x.cf +0 -0
  94. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/006_empty_file.expected.txt +0 -0
  95. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/006_empty_file.x.cf +0 -0
  96. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/007_namespace.cf +0 -0
  97. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/007_namespace.expected.txt +0 -0
  98. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/007_namespace.x.cf +0 -0
  99. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/008_bundle_shadows_function.cf +0 -0
  100. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/008_bundle_shadows_function.expected.txt +0 -0
  101. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/008_bundle_shadows_function.x.cf +0 -0
  102. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/009_unknown_function_inside_vars.cf +0 -0
  103. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/009_unknown_function_inside_vars.expected.txt +0 -0
  104. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/009_unknown_function_inside_vars.x.cf +0 -0
  105. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/010_mutually_exclusive_types_vars.cf +0 -0
  106. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/010_mutually_exclusive_types_vars.expected.txt +0 -0
  107. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/010_mutually_exclusive_types_vars.x.cf +0 -0
  108. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/011_invalid_attributes.expected.txt +0 -0
  109. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/011_invalid_attributes.x.cf +0 -0
  110. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/012_function_call_arg_count.cf +0 -0
  111. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/012_function_call_arg_count.expected.txt +0 -0
  112. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/012_function_call_arg_count.x.cf +0 -0
  113. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/013_num_args_body.expected.txt +0 -0
  114. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/013_num_args_body.x.cf +0 -0
  115. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/013_num_args_bundle.expected.txt +0 -0
  116. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/013_num_args_bundle.x.cf +0 -0
  117. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/013_num_args_bundle_body.cf +0 -0
  118. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/014_variadic_func_arg_count.cf +0 -0
  119. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/014_variadic_func_arg_count.expected.txt +0 -0
  120. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/014_variadic_func_arg_count.x.cf +0 -0
  121. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/015_macro_multi_def_bundle.cf +0 -0
  122. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/015_macro_multi_def_bundle.expected.txt +0 -0
  123. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/015_macro_multi_def_bundle.x.cf +0 -0
  124. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/016_half_promises.cf +0 -0
  125. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/016_half_promises.expected.txt +0 -0
  126. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/016_half_promises.x.cf +0 -0
  127. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/017_implies_body.cf +0 -0
  128. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/017_implies_body.expected.txt +0 -0
  129. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/017_implies_body.x.cf +0 -0
  130. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/018_nested_calls.cf +0 -0
  131. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/018_nested_calls.expected.txt +0 -0
  132. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/018_nested_calls.x.cf +0 -0
  133. {cfengine-0.16.3 → cfengine-0.16.4}/tests/lint/019_bundle_name_expansion.cf +0 -0
  134. {cfengine-0.16.3 → cfengine-0.16.4}/tests/run-format-tests.sh +0 -0
  135. {cfengine-0.16.3 → cfengine-0.16.4}/tests/run-lint-tests.sh +0 -0
  136. {cfengine-0.16.3 → cfengine-0.16.4}/tests/run-shell-tests.sh +0 -0
  137. {cfengine-0.16.3 → cfengine-0.16.4}/tests/run-up-validate-tests.sh +0 -0
  138. {cfengine-0.16.3 → cfengine-0.16.4}/tests/shell/001-help.sh +0 -0
  139. {cfengine-0.16.3 → cfengine-0.16.4}/tests/shell/002-version.sh +0 -0
  140. {cfengine-0.16.3 → cfengine-0.16.4}/tests/shell/003-format.sh +0 -0
  141. {cfengine-0.16.3 → cfengine-0.16.4}/tests/shell/004-format-check.sh +0 -0
  142. {cfengine-0.16.3 → cfengine-0.16.4}/tests/shell/005-lint.sh +0 -0
  143. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/__init__.py +0 -0
  144. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_changelog.py +0 -0
  145. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_deps.py +0 -0
  146. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_format.py +0 -0
  147. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_lint_csv.py +0 -0
  148. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_lint_yml.py +0 -0
  149. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_paths.py +0 -0
  150. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_utils.py +0 -0
  151. {cfengine-0.16.3 → cfengine-0.16.4}/tests/unit/test_version.py +0 -0
  152. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/001_complex_config.yaml +0 -0
  153. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/002_version.x.yaml +0 -0
  154. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/003_box.x.yaml +0 -0
  155. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/004_count.x.yaml +0 -0
  156. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/mocks/cloud_config.json +0 -0
  157. {cfengine-0.16.3 → cfengine-0.16.4}/tests/up-validate/mocks/vagrant +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfengine
3
- Version: 0.16.3
3
+ Version: 0.16.4
4
4
  Summary: Human-oriented CLI for interacting with CFEngine policy language, projects, and other CFEngine tools
5
5
  License: GNU GENERAL PUBLIC LICENSE
6
6
  Version 3, 29 June 2007
@@ -803,12 +803,28 @@ groups:
803
803
  spawn: ubuntu
804
804
  ```
805
805
 
806
- up will spawn the necessary VMs and install cfengine using cf-remote
806
+ `up` will spawn the necessary VMs and install cfengine using cf-remote.
807
807
 
808
- ```
808
+ ```bash
809
809
  cfengine up config.yaml
810
810
  ```
811
811
 
812
+ To validate the config, one can run:
813
+
814
+ ```bash
815
+ cfengine up --validate config.yaml
816
+ ```
817
+
818
+ Every time `up` is run, it will do all the necessary (spawn, destroy, install, uninstall) to reconciliate the current state with the input configuration.
819
+ After a successful run, the applied configuration is saved.
820
+ On subsequent runs, CFEngine compares the previously applied configuration with the current configuration and applies only the necessary changes.
821
+
822
+ To ignore the previously saved configuration and apply the current configuration as-is, run:
823
+
824
+ ```bash
825
+ cfengine up --reset config.yaml
826
+ ```
827
+
812
828
  ## Supported platforms and versions
813
829
 
814
830
  This tool will only support a limited number of platforms, it is not intended to run everywhere CFEngine runs.
@@ -99,12 +99,28 @@ groups:
99
99
  spawn: ubuntu
100
100
  ```
101
101
 
102
- up will spawn the necessary VMs and install cfengine using cf-remote
102
+ `up` will spawn the necessary VMs and install cfengine using cf-remote.
103
103
 
104
- ```
104
+ ```bash
105
105
  cfengine up config.yaml
106
106
  ```
107
107
 
108
+ To validate the config, one can run:
109
+
110
+ ```bash
111
+ cfengine up --validate config.yaml
112
+ ```
113
+
114
+ Every time `up` is run, it will do all the necessary (spawn, destroy, install, uninstall) to reconciliate the current state with the input configuration.
115
+ After a successful run, the applied configuration is saved.
116
+ On subsequent runs, CFEngine compares the previously applied configuration with the current configuration and applies only the necessary changes.
117
+
118
+ To ignore the previously saved configuration and apply the current configuration as-is, run:
119
+
120
+ ```bash
121
+ cfengine up --reset config.yaml
122
+ ```
123
+
108
124
  ## Supported platforms and versions
109
125
 
110
126
  This tool will only support a limited number of platforms, it is not intended to run everywhere CFEngine runs.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfengine
3
- Version: 0.16.3
3
+ Version: 0.16.4
4
4
  Summary: Human-oriented CLI for interacting with CFEngine policy language, projects, and other CFEngine tools
5
5
  License: GNU GENERAL PUBLIC LICENSE
6
6
  Version 3, 29 June 2007
@@ -803,12 +803,28 @@ groups:
803
803
  spawn: ubuntu
804
804
  ```
805
805
 
806
- up will spawn the necessary VMs and install cfengine using cf-remote
806
+ `up` will spawn the necessary VMs and install cfengine using cf-remote.
807
807
 
808
- ```
808
+ ```bash
809
809
  cfengine up config.yaml
810
810
  ```
811
811
 
812
+ To validate the config, one can run:
813
+
814
+ ```bash
815
+ cfengine up --validate config.yaml
816
+ ```
817
+
818
+ Every time `up` is run, it will do all the necessary (spawn, destroy, install, uninstall) to reconciliate the current state with the input configuration.
819
+ After a successful run, the applied configuration is saved.
820
+ On subsequent runs, CFEngine compares the previously applied configuration with the current configuration and applies only the necessary changes.
821
+
822
+ To ignore the previously saved configuration and apply the current configuration as-is, run:
823
+
824
+ ```bash
825
+ cfengine up --reset config.yaml
826
+ ```
827
+
812
828
  ## Supported platforms and versions
813
829
 
814
830
  This tool will only support a limited number of platforms, it is not intended to run everywhere CFEngine runs.
@@ -1,19 +1,14 @@
1
- import sys
2
1
  import os
3
2
  import re
4
3
  import json
5
4
  import yaml
6
5
  from cfengine_cli.profile import profile_cfengine, generate_callstack
7
6
  from cfengine_cli.dev import dispatch_dev_subcommand
8
- from cfengine_cli.lint import lint_args, PolicySyntaxError
7
+ from cfengine_cli.lint import lint_args
9
8
  from cfengine_cli.shell import user_command
10
9
  from cfengine_cli.paths import bin
11
10
  from cfengine_cli.version import cfengine_cli_version_string
12
- from cfengine_cli.format import (
13
- format_policy_file,
14
- format_json_file,
15
- format_policy_fin_fout,
16
- )
11
+ from cfengine_cli.format import format_paths
17
12
  from cfengine_cli.utils import UserError
18
13
  from cfengine_cli.up import validate_config
19
14
  from cfbs.commands import build_command
@@ -51,74 +46,8 @@ def deploy() -> int:
51
46
  return r
52
47
 
53
48
 
54
- def _format_filename(filename: str, line_length: int, check: bool) -> int:
55
- """Format a single file.
56
-
57
- Raises PolicySyntaxError for .cf files with syntax errors."""
58
- if filename.endswith(".json"):
59
- return format_json_file(filename, check)
60
- if filename.endswith(".cf"):
61
- return format_policy_file(filename, line_length, check)
62
- raise UserError(f"Unrecognized file format: {filename}")
63
-
64
-
65
- def _format_dirname(directory: str, line_length: int, check: bool) -> int:
66
- ret = 0
67
- for root, dirs, files in os.walk(directory):
68
- # Don't recurse into hidden folders
69
- dirs[:] = [d for d in dirs if not d.startswith(".")]
70
- for name in sorted(files):
71
- if name.startswith("."):
72
- continue # Hidden files are ignored by default
73
- if (
74
- name.endswith(".x.cf")
75
- or name.endswith(".input.cf")
76
- or name.endswith(".output.cf")
77
- or name.endswith(".expected.cf")
78
- ):
79
- continue # Test files skipped during directory traversal
80
- if name.endswith(
81
- (".input.json", ".jqinput.json", ".x.json", ".expected.json")
82
- ):
83
- continue # Test files skipped during directory traversal
84
- filepath = os.path.join(root, name)
85
- if name.endswith(".json") or name.endswith(".cf"):
86
- ret |= _format_filename(filepath, line_length, check)
87
- return ret
88
-
89
-
90
49
  def format(names, line_length, check) -> int:
91
- try:
92
- return _format_inner(names, line_length, check)
93
- except PolicySyntaxError as e:
94
- print(f"Error: {e}")
95
- return 1
96
-
97
-
98
- def _format_inner(names, line_length, check) -> int:
99
- if not names:
100
- return _format_dirname(".", line_length, check)
101
- if len(names) == 1 and names[0] == "-":
102
- # Special case, format policy file from stdin to stdout
103
- return format_policy_fin_fout(sys.stdin, sys.stdout, line_length, check)
104
-
105
- ret = 0
106
- for name in names:
107
- if name == "-":
108
- raise UserError(
109
- "The - argument has a special meaning and cannot be combined with other paths"
110
- )
111
- if not os.path.exists(name):
112
- raise UserError(f"{name} does not exist")
113
- if os.path.isfile(name):
114
- ret |= _format_filename(name, line_length, check)
115
- continue
116
- if os.path.isdir(name):
117
- ret |= _format_dirname(name, line_length, check)
118
- continue
119
- if check:
120
- return ret
121
- return 0
50
+ return format_paths(names, line_length, check)
122
51
 
123
52
 
124
53
  def _lint(files, strict) -> int:
@@ -8,7 +8,7 @@ from cfengine_cli.deptool import (
8
8
  update_dependency_tables as _update_dependency_tables,
9
9
  print_release_dependency_tables,
10
10
  )
11
- from cfengine_cli.docs import update_docs, check_docs
11
+ from cfengine_cli import docs
12
12
  from cfengine_cli.syntax_tree import syntax_tree
13
13
 
14
14
 
@@ -47,14 +47,16 @@ def print_dependency_tables(args) -> int:
47
47
  return print_release_dependency_tables(args.versions)
48
48
 
49
49
 
50
- def format_docs(files) -> int:
50
+ def format_docs() -> int:
51
51
  _expect_repo("documentation")
52
- return update_docs(files)
52
+ ret = docs.format_docs()
53
+ return ret
53
54
 
54
55
 
55
56
  def lint_docs() -> int:
56
57
  _expect_repo("documentation")
57
- return check_docs()
58
+ ret = docs.lint_docs()
59
+ return ret
58
60
 
59
61
 
60
62
  def generate_release_information(
@@ -71,7 +73,7 @@ def dispatch_dev_subcommand(subcommand, args) -> int:
71
73
  if subcommand == "print-dependency-tables":
72
74
  return print_dependency_tables(args)
73
75
  if subcommand == "format-docs":
74
- return format_docs(args.files)
76
+ return format_docs()
75
77
  if subcommand == "lint-docs":
76
78
  return lint_docs()
77
79
  if subcommand == "syntax-tree":
@@ -16,7 +16,7 @@ import markdown_it
16
16
  from cfbs.pretty import pretty_file
17
17
  from cfbs.utils import find
18
18
 
19
- from cfengine_cli.format import format_policy_file
19
+ from cfengine_cli.format import format_policy_file, format_paths
20
20
  from cfengine_cli.lint import lint_args, lint_policy_file_snippet
21
21
  from cfengine_cli.utils import UserError
22
22
 
@@ -420,12 +420,11 @@ def _run_prettier(path) -> bool:
420
420
  return formatted
421
421
 
422
422
 
423
- def _update_docs_single_arg(path):
423
+ def _format_docs_single_arg(path):
424
424
  if not os.path.exists(path):
425
425
  raise UserError(f"The specified file/folder '{path}' does not exist")
426
426
  if not os.path.isfile(path) and not os.path.isdir(path):
427
427
  raise UserError(f"Argument '{path}' is not a file or a folder")
428
-
429
428
  formatted = False
430
429
  if os.path.isdir(path) or path.endswith(".py"):
431
430
  if _run_black(path):
@@ -443,13 +442,16 @@ def _update_docs_single_arg(path):
443
442
  replace=True,
444
443
  cleanup=True,
445
444
  )
446
-
445
+ if os.path.isdir(path) or path.endswith(".cf"):
446
+ r = format_paths([path], line_length=80, check=False)
447
+ if r != 0:
448
+ formatted = True
447
449
  return formatted
448
450
 
449
451
 
450
- def update_docs(paths) -> int:
452
+ def format_docs() -> int:
451
453
  """
452
- Iterate through entire docs repo, or specified subfolders / files, autoformatting as much as possible:
454
+ Iterate through entire docs repo (CWD) autoformatting as much as possible:
453
455
  - python code with black
454
456
  - markdown files with prettier
455
457
  - code blocks inside markdown files are formatted for the formats supported by prettier
@@ -458,23 +460,27 @@ def update_docs(paths) -> int:
458
460
  Run by the command:
459
461
  cfengine dev format-docs
460
462
  """
461
- if not paths:
462
- _update_docs_single_arg(".")
463
- return 0
464
- for path in paths:
465
- _update_docs_single_arg(path)
463
+ _format_docs_single_arg(".")
466
464
  return 0
467
465
 
468
466
 
469
- def check_docs() -> int:
467
+ def lint_docs() -> int:
470
468
  """
471
469
  Run checks / tests on docs.
472
470
 
473
471
  Run by the command:
474
472
  cfengine dev lint-docs"""
473
+
474
+ # cfengine lint
475
475
  r = lint_args(["."], strict=False)
476
476
  if r != 0:
477
+ print(f"Failure - {r} errors while running cfengine lint .")
477
478
  return r
479
+
480
+ # cfengine format --check
481
+ r = format_paths(["."], line_length=80, check=True)
482
+
483
+ # Extract code blocks from markdown files and run checks on them:
478
484
  _process_markdown_code_blocks(
479
485
  path=".",
480
486
  languages=["json", "cf3"],
@@ -485,4 +491,5 @@ def check_docs() -> int:
485
491
  replace=False,
486
492
  cleanup=True,
487
493
  )
494
+ print("Success - all files look correct")
488
495
  return 0
@@ -3,11 +3,14 @@ from __future__ import annotations
3
3
  from typing import IO
4
4
 
5
5
  import json
6
+ import os
7
+ import sys
6
8
 
7
9
  import tree_sitter_cfengine as tscfengine
8
10
  from tree_sitter import Language, Parser, Node
9
11
  from cfbs.pretty import pretty_file, pretty_check_file
10
- from cfengine_cli.lint import check_policy_syntax
12
+ from cfengine_cli.lint import check_policy_syntax, PolicySyntaxError
13
+ from cfengine_cli.utils import UserError
11
14
 
12
15
  # Node types that increase indentation by 2 when entered
13
16
  INDENTED_TYPES = {
@@ -985,3 +988,79 @@ def format_policy_fin_fout(
985
988
  new_data = fmt.buffer + "\n"
986
989
  fout.write(new_data)
987
990
  return 0
991
+
992
+
993
+ def _format_filename(filename: str, line_length: int, check: bool) -> int:
994
+ """Format a single file.
995
+
996
+ Raises PolicySyntaxError for .cf files with syntax errors."""
997
+ if filename.endswith(".json"):
998
+ return format_json_file(filename, check)
999
+ if filename.endswith(".cf"):
1000
+ return format_policy_file(filename, line_length, check)
1001
+ raise UserError(f"Unrecognized file format: {filename}")
1002
+
1003
+
1004
+ def _format_dirname(directory: str, line_length: int, check: bool) -> int:
1005
+ ret = 0
1006
+ for root, dirs, files in os.walk(directory):
1007
+ # Don't recurse into hidden folders
1008
+ dirs[:] = [d for d in dirs if not d.startswith(".")]
1009
+ for name in sorted(files):
1010
+ if name.startswith("."):
1011
+ continue # Hidden files are ignored by default
1012
+ if (
1013
+ name.endswith(".x.cf")
1014
+ or name.endswith(".input.cf")
1015
+ or name.endswith(".output.cf")
1016
+ or name.endswith(".expected.cf")
1017
+ ):
1018
+ continue # Test files skipped during directory traversal
1019
+ if name.endswith(
1020
+ (".input.json", ".jqinput.json", ".x.json", ".expected.json")
1021
+ ):
1022
+ continue # Test files skipped during directory traversal
1023
+ filepath = os.path.join(root, name)
1024
+ if name.endswith(".json") or name.endswith(".cf"):
1025
+ ret |= _format_filename(filepath, line_length, check)
1026
+ return ret
1027
+
1028
+
1029
+ def _format_paths_inner(names, line_length, check) -> int:
1030
+ if not names:
1031
+ return _format_dirname(".", line_length, check)
1032
+ if len(names) == 1 and names[0] == "-":
1033
+ # Special case, format policy file from stdin to stdout
1034
+ return format_policy_fin_fout(sys.stdin, sys.stdout, line_length, check)
1035
+
1036
+ ret = 0
1037
+ for name in names:
1038
+ if name == "-":
1039
+ raise UserError(
1040
+ "The - argument has a special meaning and cannot be combined with other paths"
1041
+ )
1042
+ if not os.path.exists(name):
1043
+ raise UserError(f"{name} does not exist")
1044
+ if os.path.isfile(name):
1045
+ ret |= _format_filename(name, line_length, check)
1046
+ continue
1047
+ if os.path.isdir(name):
1048
+ ret |= _format_dirname(name, line_length, check)
1049
+ continue
1050
+ if check:
1051
+ return ret
1052
+ return 0
1053
+
1054
+
1055
+ def format_paths(names, line_length, check) -> int:
1056
+ """Format the given paths (files and/or directories), or stdin.
1057
+
1058
+ With no names, formats the current directory. A single "-" formats
1059
+ policy from stdin to stdout. Returns 0 on success (or no reformat
1060
+ needed), 1 when reformatting is needed in check mode or a policy file
1061
+ has syntax errors."""
1062
+ try:
1063
+ return _format_paths_inner(names, line_length, check)
1064
+ except PolicySyntaxError as e:
1065
+ print(f"Error: {e}")
1066
+ return 1
@@ -25,11 +25,11 @@ wheels = [
25
25
 
26
26
  [[package]]
27
27
  name = "certifi"
28
- version = "2026.5.20"
28
+ version = "2026.6.17"
29
29
  source = { registry = "https://pypi.org/simple" }
30
- sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" }
30
+ sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" }
31
31
  wheels = [
32
- { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" },
32
+ { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" },
33
33
  ]
34
34
 
35
35
  [[package]]
@@ -46,11 +46,11 @@ wheels = [
46
46
 
47
47
  [[package]]
48
48
  name = "cfbs"
49
- version = "5.6.1"
49
+ version = "5.6.2"
50
50
  source = { registry = "https://pypi.org/simple" }
51
- sdist = { url = "https://files.pythonhosted.org/packages/0d/ab/60bc20d8aae03a6ee288cdac7a9cb35778eeed974b452895e7a6d3ff5dd9/cfbs-5.6.1.tar.gz", hash = "sha256:9e50371add952f05e2f4591d6a6280d3aca5ce60ad9449910c86a20f20768781", size = 89383, upload-time = "2026-06-12T17:21:45.984Z" }
51
+ sdist = { url = "https://files.pythonhosted.org/packages/b2/46/bda65e6ee28e7bb8fa25b1b6a2ee489c9a2d58caa9c72ba2141af975309e/cfbs-5.6.2.tar.gz", hash = "sha256:25bfa7872d33e0ba78c9c794a485448216bba52ebe356e3db7e7559f22ec1001", size = 89632, upload-time = "2026-06-18T17:29:17.823Z" }
52
52
  wheels = [
53
- { url = "https://files.pythonhosted.org/packages/df/a0/a5df7ad2e2373b6c1cc8140de229da9450348bf563ae7609b13ed422544e/cfbs-5.6.1-py3-none-any.whl", hash = "sha256:8897f17f2544ccb741f95526bf35399fe7d2de504a261d7ad8f0881b7e097bb7", size = 85254, upload-time = "2026-06-12T17:21:44.63Z" },
53
+ { url = "https://files.pythonhosted.org/packages/04/30/829753a0febc5c789b6b7bcb4020314bac5aaa0346a3954390a1b377e44b/cfbs-5.6.2-py3-none-any.whl", hash = "sha256:0e24989244545c754c4165773399370ab2d1965281994e13ada3709fde77bae0", size = 85533, upload-time = "2026-06-18T17:29:16.689Z" },
54
54
  ]
55
55
 
56
56
  [[package]]
@@ -455,7 +455,7 @@ wheels = [
455
455
 
456
456
  [[package]]
457
457
  name = "pytest"
458
- version = "9.0.3"
458
+ version = "9.1.1"
459
459
  source = { registry = "https://pypi.org/simple" }
460
460
  dependencies = [
461
461
  { name = "colorama", marker = "sys_platform == 'win32'" },
@@ -466,9 +466,9 @@ dependencies = [
466
466
  { name = "pygments" },
467
467
  { name = "tomli", marker = "python_full_version < '3.11'" },
468
468
  ]
469
- sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
469
+ sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
470
470
  wheels = [
471
- { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
471
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
472
472
  ]
473
473
 
474
474
  [[package]]
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