cfengine 0.12.0__tar.gz → 0.12.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.
- {cfengine-0.12.0 → cfengine-0.12.1}/PKG-INFO +1 -1
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/PKG-INFO +1 -1
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/lint.py +64 -16
- {cfengine-0.12.0 → cfengine-0.12.1}/.github/dependabot.yml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.github/workflows/format.yml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.github/workflows/lint.yml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.github/workflows/pypi-publish.yml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.github/workflows/test.yml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.gitignore +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/.python-version +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/HACKING.md +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/LICENSE +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/README.md +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/ci/01-install.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/ci/02-safe-tests.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/ci/03-unsafe-tests.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/pyproject.toml +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/setup.cfg +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/SOURCES.txt +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/dependency_links.txt +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/entry_points.txt +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/requires.txt +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine.egg-info/top_level.txt +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/__init__.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/__main__.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/commands.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/deptool-README.md +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/deptool.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/dev.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/docs.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/format.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/main.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/__init__.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/analyze.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/check_download_matches_git.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/download.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_git_tags.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_release_information.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_vcf_download.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_vcf_git_checkout.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/paths.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/policy_language.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/profile.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/shell.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/utils.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/version.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/__init__.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/001_hello_world.expected.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/001_hello_world.input.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/002_basics.expected.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/002_basics.input.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/003_wrapping.expected.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/003_wrapping.input.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/004_comments.expected.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/format/004_comments.input.cf +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/run-format-tests.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/run-shell-tests.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/shell/001-help.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/shell/002-version.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/shell/003-format.sh +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/test_deps.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/test_paths.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/test_utils.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/tests/test_version.py +0 -0
- {cfengine-0.12.0 → cfengine-0.12.1}/uv.lock +0 -0
|
@@ -14,6 +14,7 @@ import os
|
|
|
14
14
|
import json
|
|
15
15
|
import itertools
|
|
16
16
|
import tree_sitter_cfengine as tscfengine
|
|
17
|
+
from dataclasses import dataclass
|
|
17
18
|
from tree_sitter import Language, Parser
|
|
18
19
|
from cfbs.validate import validate_config
|
|
19
20
|
from cfbs.cfbs_config import CFBSConfig
|
|
@@ -26,6 +27,39 @@ from cfengine_cli.policy_language import (
|
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
@dataclass
|
|
31
|
+
class _State:
|
|
32
|
+
block_type: str | None = None # "bundle" | "body" | "promise" | None
|
|
33
|
+
promise_type: str | None = None # "vars" | "files" | "classes" | ... | None
|
|
34
|
+
attribute_name: str | None = None # "if" | "string" | "slist" | ... | None
|
|
35
|
+
|
|
36
|
+
def update(self, node) -> "_State":
|
|
37
|
+
"""Updates and returns the state that should apply to the children of `node`."""
|
|
38
|
+
if node.type == "bundle_block":
|
|
39
|
+
return _State(block_type="bundle")
|
|
40
|
+
if node.type == "body_block":
|
|
41
|
+
return _State(block_type="body")
|
|
42
|
+
if node.type == "promise_block":
|
|
43
|
+
return _State(block_type="promise")
|
|
44
|
+
if node.type == "bundle_section":
|
|
45
|
+
for child in node.children:
|
|
46
|
+
if child.type == "promise_guard":
|
|
47
|
+
return _State(
|
|
48
|
+
block_type=self.block_type,
|
|
49
|
+
promise_type=_text(child)[:-1], # strip trailing ':'
|
|
50
|
+
)
|
|
51
|
+
return _State(block_type=self.block_type)
|
|
52
|
+
if node.type == "attribute":
|
|
53
|
+
for child in node.children:
|
|
54
|
+
if child.type == "attribute_name":
|
|
55
|
+
return _State(
|
|
56
|
+
block_type=self.block_type,
|
|
57
|
+
promise_type=self.promise_type,
|
|
58
|
+
attribute_name=_text(child),
|
|
59
|
+
)
|
|
60
|
+
return self
|
|
61
|
+
|
|
62
|
+
|
|
29
63
|
def lint_cfbs_json(filename) -> int:
|
|
30
64
|
assert os.path.isfile(filename)
|
|
31
65
|
assert filename.endswith("cfbs.json")
|
|
@@ -93,16 +127,9 @@ def _find_node_type(filename, lines, node, node_type):
|
|
|
93
127
|
return matches
|
|
94
128
|
|
|
95
129
|
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
_walk_generic(filename, lines, node, visitor)
|
|
100
|
-
return matches
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def _single_node_checks(filename, lines, node, user_definition, strict):
|
|
104
|
-
"""Things which can be checked by only looking at one node,
|
|
105
|
-
not needing to recurse into children."""
|
|
130
|
+
def _node_checks(filename, lines, node, user_definition, strict, state: _State):
|
|
131
|
+
"""Checks we run on each node in the syntax tree,
|
|
132
|
+
utilizes state for checks which require context."""
|
|
106
133
|
line = node.range.start_point[0] + 1
|
|
107
134
|
column = node.range.start_point[1] + 1
|
|
108
135
|
if node.type == "attribute_name" and _text(node) == "ifvarclass":
|
|
@@ -133,7 +160,6 @@ def _single_node_checks(filename, lines, node, user_definition, strict):
|
|
|
133
160
|
f"Error: Undefined promise type '{promise_type}' at {filename}:{line}:{column}"
|
|
134
161
|
)
|
|
135
162
|
return 1
|
|
136
|
-
|
|
137
163
|
if node.type == "bundle_block_name":
|
|
138
164
|
if _text(node) != _text(node).lower():
|
|
139
165
|
_highlight_range(node, lines)
|
|
@@ -156,6 +182,16 @@ def _single_node_checks(filename, lines, node, user_definition, strict):
|
|
|
156
182
|
)
|
|
157
183
|
return 1
|
|
158
184
|
if node.type == "calling_identifier":
|
|
185
|
+
if (
|
|
186
|
+
strict
|
|
187
|
+
and _text(node) in user_definition.get("all_bundle_names", set())
|
|
188
|
+
and state.promise_type in user_definition.get("custom_promise_types", set())
|
|
189
|
+
):
|
|
190
|
+
_highlight_range(node, lines)
|
|
191
|
+
print(
|
|
192
|
+
f"Error: Call to bundle '{_text(node)}' inside custom promise: '{state.promise_type}' at {filename}:{line}:{column}"
|
|
193
|
+
)
|
|
194
|
+
return 1
|
|
159
195
|
if strict and (
|
|
160
196
|
_text(node)
|
|
161
197
|
not in BUILTIN_FUNCTIONS.union(
|
|
@@ -171,6 +207,22 @@ def _single_node_checks(filename, lines, node, user_definition, strict):
|
|
|
171
207
|
return 0
|
|
172
208
|
|
|
173
209
|
|
|
210
|
+
def _stateful_walk(
|
|
211
|
+
filename, lines, node, user_definition, strict, state: _State | None = None
|
|
212
|
+
) -> int:
|
|
213
|
+
if state is None:
|
|
214
|
+
state = _State()
|
|
215
|
+
|
|
216
|
+
errors = _node_checks(filename, lines, node, user_definition, strict, state)
|
|
217
|
+
|
|
218
|
+
child_state = state.update(node)
|
|
219
|
+
for child in node.children:
|
|
220
|
+
errors += _stateful_walk(
|
|
221
|
+
filename, lines, child, user_definition, strict, child_state
|
|
222
|
+
)
|
|
223
|
+
return errors
|
|
224
|
+
|
|
225
|
+
|
|
174
226
|
def _walk(filename, lines, node, user_definition=None, strict=True) -> int:
|
|
175
227
|
if user_definition is None:
|
|
176
228
|
user_definition = {}
|
|
@@ -187,11 +239,7 @@ def _walk(filename, lines, node, user_definition=None, strict=True) -> int:
|
|
|
187
239
|
line = node.range.start_point[0] + 1
|
|
188
240
|
column = node.range.start_point[1] + 1
|
|
189
241
|
|
|
190
|
-
|
|
191
|
-
for node in _find_nodes(filename, lines, node):
|
|
192
|
-
errors += _single_node_checks(filename, lines, node, user_definition, strict)
|
|
193
|
-
|
|
194
|
-
return errors
|
|
242
|
+
return _stateful_walk(filename, lines, node, user_definition, strict)
|
|
195
243
|
|
|
196
244
|
|
|
197
245
|
def _parse_user_definition(filename, lines, root_node):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/check_download_matches_git.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_release_information.py
RENAMED
|
File without changes
|
|
File without changes
|
{cfengine-0.12.0 → cfengine-0.12.1}/src/cfengine_cli/masterfiles/generate_vcf_git_checkout.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|