cfengine 0.16.7__tar.gz → 0.17.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 (162) hide show
  1. {cfengine-0.16.7 → cfengine-0.17.0}/PKG-INFO +1 -1
  2. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/PKG-INFO +1 -1
  3. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/SOURCES.txt +2 -0
  4. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/scm_file_list.json +2 -0
  5. cfengine-0.17.0/src/cfengine.egg-info/scm_version.json +8 -0
  6. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/format.py +67 -4
  7. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/syntax-description.json +16 -2
  8. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/004_comments.expected.cf +3 -6
  9. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/005_bundle_comments.expected.cf +1 -2
  10. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/010_stakeholder.expected.cf +2 -4
  11. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/011_promises.expected.cf +5 -14
  12. cfengine-0.17.0/tests/format/012_sameline_comments.expected.cf +25 -0
  13. cfengine-0.17.0/tests/format/012_sameline_comments.input.cf +23 -0
  14. cfengine-0.16.7/src/cfengine.egg-info/scm_version.json +0 -8
  15. {cfengine-0.16.7 → cfengine-0.17.0}/.github/dependabot.yml +0 -0
  16. {cfengine-0.16.7 → cfengine-0.17.0}/.github/workflows/lint-policy-in-other-repos.yml +0 -0
  17. {cfengine-0.16.7 → cfengine-0.17.0}/.github/workflows/make-check.yml +0 -0
  18. {cfengine-0.16.7 → cfengine-0.17.0}/.github/workflows/pypi-publish.yml +0 -0
  19. {cfengine-0.16.7 → cfengine-0.17.0}/.github/workflows/stale.yml +0 -0
  20. {cfengine-0.16.7 → cfengine-0.17.0}/.github/workflows/update-syntax-description.yml +0 -0
  21. {cfengine-0.16.7 → cfengine-0.17.0}/.gitignore +0 -0
  22. {cfengine-0.16.7 → cfengine-0.17.0}/.python-version +0 -0
  23. {cfengine-0.16.7 → cfengine-0.17.0}/CLAUDE.md +0 -0
  24. {cfengine-0.16.7 → cfengine-0.17.0}/HACKING.md +0 -0
  25. {cfengine-0.16.7 → cfengine-0.17.0}/LICENSE +0 -0
  26. {cfengine-0.16.7 → cfengine-0.17.0}/Makefile +0 -0
  27. {cfengine-0.16.7 → cfengine-0.17.0}/README.md +0 -0
  28. {cfengine-0.16.7 → cfengine-0.17.0}/ci/01-install.sh +0 -0
  29. {cfengine-0.16.7 → cfengine-0.17.0}/ci/02-safe-tests.sh +0 -0
  30. {cfengine-0.16.7 → cfengine-0.17.0}/ci/03-unsafe-tests.sh +0 -0
  31. {cfengine-0.16.7 → cfengine-0.17.0}/pyproject.toml +0 -0
  32. {cfengine-0.16.7 → cfengine-0.17.0}/setup.cfg +0 -0
  33. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/dependency_links.txt +0 -0
  34. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/entry_points.txt +0 -0
  35. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/requires.txt +0 -0
  36. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine.egg-info/top_level.txt +0 -0
  37. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/__init__.py +0 -0
  38. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/__main__.py +0 -0
  39. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/changelog.py +0 -0
  40. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/commands.py +0 -0
  41. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/deptool-README.md +0 -0
  42. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/deptool.py +0 -0
  43. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/dev.py +0 -0
  44. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/docs.py +0 -0
  45. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/lint.py +0 -0
  46. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/lint_csv.py +0 -0
  47. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/lint_yml.py +0 -0
  48. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/main.py +0 -0
  49. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/__init__.py +0 -0
  50. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/analyze.py +0 -0
  51. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/check_download_matches_git.py +0 -0
  52. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/download.py +0 -0
  53. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/generate_git_tags.py +0 -0
  54. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/generate_release_information.py +0 -0
  55. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/generate_vcf_download.py +0 -0
  56. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/masterfiles/generate_vcf_git_checkout.py +0 -0
  57. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/paths.py +0 -0
  58. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/profile.py +0 -0
  59. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/shell.py +0 -0
  60. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/syntax_tree.py +0 -0
  61. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/up.py +0 -0
  62. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/utils.py +0 -0
  63. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/validate.py +0 -0
  64. {cfengine-0.16.7 → cfengine-0.17.0}/src/cfengine_cli/version.py +0 -0
  65. {cfengine-0.16.7 → cfengine-0.17.0}/tests/README.md +0 -0
  66. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/001_hello_world.expected.cf +0 -0
  67. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/001_hello_world.input.cf +0 -0
  68. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/002_basics.expected.cf +0 -0
  69. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/002_basics.input.cf +0 -0
  70. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/003_wrapping.expected.cf +0 -0
  71. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/003_wrapping.input.cf +0 -0
  72. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/004_comments.input.cf +0 -0
  73. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/005_bundle_comments.input.cf +0 -0
  74. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/006_remove_empty_comments.expected.cf +0 -0
  75. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/006_remove_empty_comments.input.cf +0 -0
  76. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/007_class_guarded_empty_lines.expected.cf +0 -0
  77. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/007_class_guarded_empty_lines.input.cf +0 -0
  78. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/008_long_string.expected.cf +0 -0
  79. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/008_long_string.input.cf +0 -0
  80. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/009_single_line.expected.cf +0 -0
  81. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/009_single_line.input.cf +0 -0
  82. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/010_stakeholder.input.cf +0 -0
  83. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/011_macros.expected.cf +0 -0
  84. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/011_macros.input.cf +0 -0
  85. {cfengine-0.16.7 → cfengine-0.17.0}/tests/format/011_promises.input.cf +0 -0
  86. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/001_hello_world.cf +0 -0
  87. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/002_deprecations.expected.txt +0 -0
  88. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/002_deprecations.x.cf +0 -0
  89. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/003_name_lowercase.cf +0 -0
  90. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/003_name_lowercase.expected.txt +0 -0
  91. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/003_name_lowercase.x.cf +0 -0
  92. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/004_block_type.cf +0 -0
  93. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/004_block_type.expected.txt +0 -0
  94. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/004_block_type.x.cf +0 -0
  95. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/005_syntax_error.cf +0 -0
  96. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/005_syntax_error.expected.txt +0 -0
  97. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/005_syntax_error.x.cf +0 -0
  98. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/006_empty_file.expected.txt +0 -0
  99. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/006_empty_file.x.cf +0 -0
  100. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/007_namespace.cf +0 -0
  101. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/007_namespace.expected.txt +0 -0
  102. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/007_namespace.x.cf +0 -0
  103. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/008_bundle_shadows_function.cf +0 -0
  104. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/008_bundle_shadows_function.expected.txt +0 -0
  105. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/008_bundle_shadows_function.x.cf +0 -0
  106. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/009_unknown_function_inside_vars.cf +0 -0
  107. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/009_unknown_function_inside_vars.expected.txt +0 -0
  108. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/009_unknown_function_inside_vars.x.cf +0 -0
  109. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/010_mutually_exclusive_types_vars.cf +0 -0
  110. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/010_mutually_exclusive_types_vars.expected.txt +0 -0
  111. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/010_mutually_exclusive_types_vars.x.cf +0 -0
  112. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/011_invalid_attributes.expected.txt +0 -0
  113. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/011_invalid_attributes.x.cf +0 -0
  114. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/012_function_call_arg_count.cf +0 -0
  115. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/012_function_call_arg_count.expected.txt +0 -0
  116. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/012_function_call_arg_count.x.cf +0 -0
  117. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/013_num_args_body.expected.txt +0 -0
  118. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/013_num_args_body.x.cf +0 -0
  119. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/013_num_args_bundle.expected.txt +0 -0
  120. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/013_num_args_bundle.x.cf +0 -0
  121. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/013_num_args_bundle_body.cf +0 -0
  122. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/014_variadic_func_arg_count.cf +0 -0
  123. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/014_variadic_func_arg_count.expected.txt +0 -0
  124. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/014_variadic_func_arg_count.x.cf +0 -0
  125. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/015_macro_multi_def_bundle.cf +0 -0
  126. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/015_macro_multi_def_bundle.expected.txt +0 -0
  127. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/015_macro_multi_def_bundle.x.cf +0 -0
  128. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/016_half_promises.cf +0 -0
  129. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/016_half_promises.expected.txt +0 -0
  130. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/016_half_promises.x.cf +0 -0
  131. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/017_implies_body.cf +0 -0
  132. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/017_implies_body.expected.txt +0 -0
  133. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/017_implies_body.x.cf +0 -0
  134. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/018_nested_calls.cf +0 -0
  135. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/018_nested_calls.expected.txt +0 -0
  136. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/018_nested_calls.x.cf +0 -0
  137. {cfengine-0.16.7 → cfengine-0.17.0}/tests/lint/019_bundle_name_expansion.cf +0 -0
  138. {cfengine-0.16.7 → cfengine-0.17.0}/tests/run-format-tests.sh +0 -0
  139. {cfengine-0.16.7 → cfengine-0.17.0}/tests/run-lint-tests.sh +0 -0
  140. {cfengine-0.16.7 → cfengine-0.17.0}/tests/run-shell-tests.sh +0 -0
  141. {cfengine-0.16.7 → cfengine-0.17.0}/tests/run-up-validate-tests.sh +0 -0
  142. {cfengine-0.16.7 → cfengine-0.17.0}/tests/shell/001-help.sh +0 -0
  143. {cfengine-0.16.7 → cfengine-0.17.0}/tests/shell/002-version.sh +0 -0
  144. {cfengine-0.16.7 → cfengine-0.17.0}/tests/shell/003-format.sh +0 -0
  145. {cfengine-0.16.7 → cfengine-0.17.0}/tests/shell/004-format-check.sh +0 -0
  146. {cfengine-0.16.7 → cfengine-0.17.0}/tests/shell/005-lint.sh +0 -0
  147. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/__init__.py +0 -0
  148. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_changelog.py +0 -0
  149. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_deps.py +0 -0
  150. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_format.py +0 -0
  151. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_lint_csv.py +0 -0
  152. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_lint_yml.py +0 -0
  153. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_paths.py +0 -0
  154. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_utils.py +0 -0
  155. {cfengine-0.16.7 → cfengine-0.17.0}/tests/unit/test_version.py +0 -0
  156. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/001_complex_config.yaml +0 -0
  157. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/002_version.x.yaml +0 -0
  158. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/003_box.x.yaml +0 -0
  159. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/004_count.x.yaml +0 -0
  160. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/mocks/cloud_config.json +0 -0
  161. {cfengine-0.16.7 → cfengine-0.17.0}/tests/up-validate/mocks/vagrant +0 -0
  162. {cfengine-0.16.7 → cfengine-0.17.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfengine
3
- Version: 0.16.7
3
+ Version: 0.17.0
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfengine
3
- Version: 0.16.7
3
+ Version: 0.17.0
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
@@ -83,6 +83,8 @@ tests/format/011_macros.expected.cf
83
83
  tests/format/011_macros.input.cf
84
84
  tests/format/011_promises.expected.cf
85
85
  tests/format/011_promises.input.cf
86
+ tests/format/012_sameline_comments.expected.cf
87
+ tests/format/012_sameline_comments.input.cf
86
88
  tests/lint/001_hello_world.cf
87
89
  tests/lint/002_deprecations.expected.txt
88
90
  tests/lint/002_deprecations.x.cf
@@ -130,9 +130,11 @@
130
130
  "tests/format/004_comments.input.cf",
131
131
  "tests/format/001_hello_world.expected.cf",
132
132
  "tests/format/011_promises.input.cf",
133
+ "tests/format/012_sameline_comments.expected.cf",
133
134
  "tests/format/008_long_string.expected.cf",
134
135
  "tests/format/008_long_string.input.cf",
135
136
  "tests/format/002_basics.input.cf",
137
+ "tests/format/012_sameline_comments.input.cf",
136
138
  "tests/format/011_macros.input.cf",
137
139
  "tests/unit/__init__.py",
138
140
  "tests/unit/test_version.py",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.17.0",
3
+ "distance": 0,
4
+ "node": "g052defd5991547f1ddcc7c1eb64f5ca22682be34",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-07-01"
8
+ }
@@ -35,6 +35,8 @@ BLOCK_BODY_TYPES = {"bundle_block_body", "promise_block_body", "body_block_body"
35
35
 
36
36
  PROMISER_PARTS = {"promiser", "->", "stakeholder"}
37
37
 
38
+ SAMELINE_COMMENT_SEPARATOR = " "
39
+
38
40
 
39
41
  def _has_direct_macro(node: Node) -> bool:
40
42
  """Check if any direct child of a node is a macro (non-recursive)."""
@@ -241,6 +243,9 @@ def split_generic_list(
241
243
  # outside the function call, so we do not add trailing commas into function
242
244
  # call argument lists.
243
245
  value_end_indices: list[int] = []
246
+ # Same-line (trailing) comments are attached only after trailing commas are
247
+ # placed, so the comma lands before the comment instead of after it.
248
+ sameline_comments: dict[int, str] = {}
244
249
  for element in middle:
245
250
  if elements and element.type == ",":
246
251
  elements[-1] = elements[-1] + ","
@@ -249,7 +254,10 @@ def split_generic_list(
249
254
  elements.append(text(element))
250
255
  continue
251
256
  if element.type == "comment":
252
- elements.append(" " * indent + text(element))
257
+ if _is_sameline_comment(element) and elements:
258
+ sameline_comments[len(elements) - 1] = text(element)
259
+ else:
260
+ elements.append(" " * indent + text(element))
253
261
  continue
254
262
  line = " " * indent + stringify_single_line_node(element)
255
263
  # Strict < reserves 1 char for the comma appended after this check
@@ -275,6 +283,10 @@ def split_generic_list(
275
283
  if not elements[i].lstrip().startswith("#"):
276
284
  elements[i] = _set_trailing_comma(elements[i], trailing_comma)
277
285
  break
286
+
287
+ # Attach same-line comments to the end of their value lines
288
+ for i, comment in sameline_comments.items():
289
+ elements[i] = elements[i] + SAMELINE_COMMENT_SEPARATOR + comment
278
290
  return elements
279
291
 
280
292
 
@@ -354,7 +366,10 @@ def _format_attribute_with_macros(node: Node, indent: int) -> list[str]:
354
366
  if child.type == "macro":
355
367
  lines.append(text(child))
356
368
  elif child.type == "comment":
357
- lines.append(" " * (indent + 2) + text(child))
369
+ if _is_sameline_comment(child) and lines:
370
+ lines[-1] = lines[-1] + SAMELINE_COMMENT_SEPARATOR + text(child)
371
+ else:
372
+ lines.append(" " * (indent + 2) + text(child))
358
373
  else:
359
374
  lines.append(" " * (indent + 2) + stringify_single_line_node(child))
360
375
 
@@ -505,13 +520,19 @@ def _format_stakeholder_elements(
505
520
  return maybe_split_generic_list(middle, indent, line_length)
506
521
  # Comments present — format element-by-element to preserve them
507
522
  elements: list[str] = []
523
+ # Same-line (trailing) comments are attached only after the trailing comma is
524
+ # placed, so the comma lands before the comment instead of after it.
525
+ sameline_comments: dict[int, str] = {}
508
526
  for node in middle:
509
527
  if node.type == ",":
510
528
  if elements:
511
529
  elements[-1] = elements[-1] + ","
512
530
  continue
513
531
  if node.type == "comment":
514
- elements.append(" " * indent + text(node))
532
+ if _is_sameline_comment(node) and elements:
533
+ sameline_comments[len(elements) - 1] = text(node)
534
+ else:
535
+ elements.append(" " * indent + text(node))
515
536
  else:
516
537
  line = " " * indent + stringify_single_line_node(node)
517
538
  # Strict < reserves 1 char for the comma appended after this check
@@ -528,6 +549,10 @@ def _format_stakeholder_elements(
528
549
  if not elements[i].endswith(","):
529
550
  elements[i] = elements[i] + ","
530
551
  break
552
+
553
+ # Attach inline comments to the end of their value lines
554
+ for i, comment in sameline_comments.items():
555
+ elements[i] = elements[i] + SAMELINE_COMMENT_SEPARATOR + comment
531
556
  return elements
532
557
 
533
558
 
@@ -682,9 +707,13 @@ def _format_block_header(node: Node, fmt: Formatter) -> list[Node]:
682
707
  """Format a block header line and return the body's children for further processing."""
683
708
  header_parts: list[str] = []
684
709
  header_comments: list[str] = []
710
+ # Direct comment children of the block (excludes comments inside a
711
+ # parameter list) — candidates for being kept on the header line.
712
+ direct_comments: list[Node] = []
685
713
  for x in node.children[0:-1]:
686
714
  if x.type == "comment":
687
715
  header_comments.append(text(x))
716
+ direct_comments.append(x)
688
717
  elif x.type == "parameter_list":
689
718
  parts: list[str] = []
690
719
  for p in x.children:
@@ -696,6 +725,16 @@ def _format_block_header(node: Node, fmt: Formatter) -> list[Node]:
696
725
  else:
697
726
  header_parts.append(text(x))
698
727
  line = " ".join(header_parts)
728
+ # A lone same-line comment stays on the header line. When the header has
729
+ # more than one comment, keep them together on their own lines below the
730
+ # header instead of splitting one off onto the header line.
731
+ if (
732
+ len(header_comments) == 1
733
+ and len(direct_comments) == 1
734
+ and _is_sameline_comment(direct_comments[0])
735
+ ):
736
+ line += SAMELINE_COMMENT_SEPARATOR + header_comments[0]
737
+ header_comments = []
699
738
  if not fmt.empty:
700
739
  prev_sib = node.prev_named_sibling
701
740
  # Skip over preceding empty comments since they will be removed
@@ -725,6 +764,11 @@ def _format_block_header(node: Node, fmt: Formatter) -> list[Node]:
725
764
 
726
765
  def _needs_blank_line_before(child: Node, indent: int, line_length: int) -> bool:
727
766
  """Check if a blank separator line should precede this child node."""
767
+ # Inline (trailing) comments are appended to the preceding line, so they
768
+ # must never be preceded by a blank separator line.
769
+ if child.type == "comment" and _is_sameline_comment(child):
770
+ return False
771
+
728
772
  prev = child.prev_named_sibling
729
773
  # Empty comments preceding this child will be dropped — look past them
730
774
  # so we evaluate against the real prior content.
@@ -798,6 +842,21 @@ def _needs_blank_line_before(child: Node, indent: int, line_length: int) -> bool
798
842
  # ---------------------------------------------------------------------------
799
843
 
800
844
 
845
+ def _is_sameline_comment(node: Node) -> bool:
846
+ """Check if a comment sits on the same source line as the element before it.
847
+
848
+ A trailing comment shares the row of the preceding sibling (which may be
849
+ a leaf like ',' or ';', or a whole promise/attribute). Such comments are
850
+ kept on the same output line as that element rather than moved to their
851
+ own line."""
852
+ if node.type != "comment":
853
+ return False
854
+ prev = node.prev_sibling
855
+ if prev is None:
856
+ return False
857
+ return prev.end_point[0] == node.start_point[0]
858
+
859
+
801
860
  def _is_empty_comment(node: Node) -> bool:
802
861
  """Check if a bare '#' comment should be dropped.
803
862
 
@@ -934,7 +993,11 @@ def _autoformat(
934
993
  else:
935
994
  fmt.print_same_line(node)
936
995
  elif node.type == "comment":
937
- if not _is_empty_comment(node):
996
+ if _is_empty_comment(node):
997
+ pass
998
+ elif _is_sameline_comment(node) and not fmt.empty:
999
+ fmt.print_same_line(SAMELINE_COMMENT_SEPARATOR + text(node))
1000
+ else:
938
1001
  fmt.print(node, _comment_indent(node, indent))
939
1002
  else:
940
1003
  fmt.print(node, indent)
@@ -753,7 +753,7 @@
753
753
  },
754
754
  "protocol_version": {
755
755
  "attribute": "protocol_version",
756
- "range": "1,classic,2,tls,3,cookie,4,filestream,latest",
756
+ "range": "1,classic,2,tls,3,cookie,4,filestream,5,leech2,latest",
757
757
  "status": "normal",
758
758
  "type": "option",
759
759
  "visibility": "body"
@@ -1020,7 +1020,7 @@
1020
1020
  },
1021
1021
  "protocol_version": {
1022
1022
  "attribute": "protocol_version",
1023
- "range": "1,classic,2,tls,3,cookie,4,filestream,latest",
1023
+ "range": "1,classic,2,tls,3,cookie,4,filestream,5,leech2,latest",
1024
1024
  "status": "normal",
1025
1025
  "type": "option",
1026
1026
  "visibility": "body"
@@ -7368,6 +7368,13 @@
7368
7368
  "type": "clist",
7369
7369
  "visibility": "promiseType"
7370
7370
  },
7371
+ "cancel": {
7372
+ "attribute": "cancel",
7373
+ "range": "true,false,yes,no,on,off",
7374
+ "status": "normal",
7375
+ "type": "option",
7376
+ "visibility": "promiseType"
7377
+ },
7371
7378
  "classes": {
7372
7379
  "attribute": "classes",
7373
7380
  "status": "normal",
@@ -7465,6 +7472,13 @@
7465
7472
  "type": "clist",
7466
7473
  "visibility": "promiseType"
7467
7474
  },
7475
+ "timer_policy": {
7476
+ "attribute": "timer_policy",
7477
+ "range": "absolute,reset",
7478
+ "status": "normal",
7479
+ "type": "option",
7480
+ "visibility": "promiseType"
7481
+ },
7468
7482
  "unless": {
7469
7483
  "attribute": "unless",
7470
7484
  "range": "",
@@ -52,17 +52,14 @@ bundle agent win_services
52
52
  "autostart_services"
53
53
  slist => {
54
54
  "Alerter",
55
- "W32Time",
56
- # Windows Time
55
+ "W32Time", # Windows Time
57
56
  };
58
57
 
59
58
  some_class::
60
59
  "autostart_services"
61
60
  slist => {
62
- "MpsSvc",
63
- # Windows Firewall
64
- "W32Time",
65
- # Windows Time
61
+ "MpsSvc", # Windows Firewall
62
+ "W32Time", # Windows Time
66
63
  };
67
64
 
68
65
  some_class::
@@ -1,5 +1,4 @@
1
- bundle agent a
2
- # @brief Description of a
1
+ bundle agent a # @brief Description of a
3
2
  {
4
3
  reports:
5
4
  "Hello, world!";
@@ -111,9 +111,7 @@ bundle agent yoda_two
111
111
  {
112
112
  reports:
113
113
  "hi" -> {
114
- "yoda",
115
- # this is yoda of course
116
- "boba",
117
- # and yet another star wars character
114
+ "yoda", # this is yoda of course
115
+ "boba", # and yet another star wars character
118
116
  };
119
117
  }
@@ -43,8 +43,7 @@ body common control
43
43
  services_autorun,
44
44
  @(services_autorun.bundles),
45
45
  # Agent bundle
46
- cfe_internal_management,
47
- # See cfe_internal/CFE_cfengine.cf
46
+ cfe_internal_management, # See cfe_internal/CFE_cfengine.cf
48
47
  mpf_main,
49
48
  @(cfengine_enterprise_hub_ha.management_bundles),
50
49
  @(def.bundlesequence_end),
@@ -125,13 +124,9 @@ body common control
125
124
  lastseenexpireafter => "$(def.control_common_lastseenexpireafter)";
126
125
 
127
126
  control_common_tls_min_version_defined::
128
- tls_min_version => "$(default:def.control_common_tls_min_version)";
129
-
130
- # See also: allowtlsversion in body server control
127
+ tls_min_version => "$(default:def.control_common_tls_min_version)"; # See also: allowtlsversion in body server control
131
128
  control_common_tls_ciphers_defined::
132
- tls_ciphers => "$(default:def.control_common_tls_ciphers)";
133
-
134
- # See also: allowciphers in body server control
129
+ tls_ciphers => "$(default:def.control_common_tls_ciphers)"; # See also: allowciphers in body server control
135
130
  control_common_system_log_level_defined::
136
131
  system_log_level => "$(default:def.control_common_system_log_level)";
137
132
 
@@ -500,14 +495,10 @@ bundle common services_autorun
500
495
  # automatically.
501
496
  "inputs" slist => {};
502
497
  "found_inputs" slist => {};
503
- "bundles" slist => { "services_autorun" };
504
-
505
- # run self
498
+ "bundles" slist => { "services_autorun" }; # run self
506
499
  services_autorun|services_autorun_inputs|services_autorun_bundles::
507
500
  "inputs" slist => { "$(sys.local_libdir)/autorun.cf" };
508
- "bundles" slist => { "autorun" };
509
-
510
- # run loaded bundles
501
+ "bundles" slist => { "autorun" }; # run loaded bundles
511
502
  reports:
512
503
  DEBUG|DEBUG_services_autorun::
513
504
  "DEBUG $(this.bundle): Services Autorun Disabled"
@@ -0,0 +1,25 @@
1
+ bundle agent main
2
+ {
3
+ vars:
4
+ "x" string => "y"; # trailing comment after promise
5
+ "list"
6
+ slist => {
7
+ "a", # first element
8
+ "b",
9
+ "c", # third element
10
+ };
11
+
12
+ "multi"
13
+ if => "something", # condition comment
14
+ string => "value"; # value comment
15
+ "own_line"
16
+ # this comment is on its own line
17
+ string => "value";
18
+ }
19
+
20
+ body package_method apt
21
+ {
22
+ package_changes => "bulk"; # bulk method
23
+ # standalone comment
24
+ package_list_command => "/usr/bin/dpkg -l";
25
+ }
@@ -0,0 +1,23 @@
1
+ bundle agent main
2
+ {
3
+ vars:
4
+ "x" string => "y"; # trailing comment after promise
5
+ "list" slist => {
6
+ "a", # first element
7
+ "b",
8
+ "c", # third element
9
+ };
10
+ "multi"
11
+ if => "something", # condition comment
12
+ string => "value"; # value comment
13
+ "own_line"
14
+ # this comment is on its own line
15
+ string => "value";
16
+ }
17
+
18
+ body package_method apt
19
+ {
20
+ package_changes => "bulk"; # bulk method
21
+ # standalone comment
22
+ package_list_command => "/usr/bin/dpkg -l";
23
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.16.7",
3
- "distance": 0,
4
- "node": "g474858503e26c363933858d6151cf3d00924b70e",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-06-25"
8
- }
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