cfengine 0.11.2__tar.gz → 0.12.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 (65) hide show
  1. {cfengine-0.11.2 → cfengine-0.12.0}/PKG-INFO +1 -1
  2. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/PKG-INFO +1 -1
  3. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/SOURCES.txt +1 -0
  4. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/commands.py +6 -7
  5. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/docs.py +1 -1
  6. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/lint.py +105 -21
  7. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/main.py +7 -1
  8. cfengine-0.12.0/src/cfengine_cli/policy_language.py +239 -0
  9. {cfengine-0.11.2 → cfengine-0.12.0}/uv.lock +3 -3
  10. {cfengine-0.11.2 → cfengine-0.12.0}/.github/dependabot.yml +0 -0
  11. {cfengine-0.11.2 → cfengine-0.12.0}/.github/workflows/format.yml +0 -0
  12. {cfengine-0.11.2 → cfengine-0.12.0}/.github/workflows/lint.yml +0 -0
  13. {cfengine-0.11.2 → cfengine-0.12.0}/.github/workflows/pypi-publish.yml +0 -0
  14. {cfengine-0.11.2 → cfengine-0.12.0}/.github/workflows/test.yml +0 -0
  15. {cfengine-0.11.2 → cfengine-0.12.0}/.gitignore +0 -0
  16. {cfengine-0.11.2 → cfengine-0.12.0}/.python-version +0 -0
  17. {cfengine-0.11.2 → cfengine-0.12.0}/HACKING.md +0 -0
  18. {cfengine-0.11.2 → cfengine-0.12.0}/LICENSE +0 -0
  19. {cfengine-0.11.2 → cfengine-0.12.0}/README.md +0 -0
  20. {cfengine-0.11.2 → cfengine-0.12.0}/ci/01-install.sh +0 -0
  21. {cfengine-0.11.2 → cfengine-0.12.0}/ci/02-safe-tests.sh +0 -0
  22. {cfengine-0.11.2 → cfengine-0.12.0}/ci/03-unsafe-tests.sh +0 -0
  23. {cfengine-0.11.2 → cfengine-0.12.0}/pyproject.toml +0 -0
  24. {cfengine-0.11.2 → cfengine-0.12.0}/setup.cfg +0 -0
  25. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/dependency_links.txt +0 -0
  26. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/entry_points.txt +0 -0
  27. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/requires.txt +0 -0
  28. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine.egg-info/top_level.txt +0 -0
  29. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/__init__.py +0 -0
  30. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/__main__.py +0 -0
  31. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/deptool-README.md +0 -0
  32. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/deptool.py +0 -0
  33. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/dev.py +0 -0
  34. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/format.py +0 -0
  35. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/__init__.py +0 -0
  36. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/analyze.py +0 -0
  37. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/check_download_matches_git.py +0 -0
  38. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/download.py +0 -0
  39. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/generate_git_tags.py +0 -0
  40. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/generate_release_information.py +0 -0
  41. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/generate_vcf_download.py +0 -0
  42. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/masterfiles/generate_vcf_git_checkout.py +0 -0
  43. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/paths.py +0 -0
  44. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/profile.py +0 -0
  45. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/shell.py +0 -0
  46. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/utils.py +0 -0
  47. {cfengine-0.11.2 → cfengine-0.12.0}/src/cfengine_cli/version.py +0 -0
  48. {cfengine-0.11.2 → cfengine-0.12.0}/tests/__init__.py +0 -0
  49. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/001_hello_world.expected.cf +0 -0
  50. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/001_hello_world.input.cf +0 -0
  51. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/002_basics.expected.cf +0 -0
  52. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/002_basics.input.cf +0 -0
  53. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/003_wrapping.expected.cf +0 -0
  54. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/003_wrapping.input.cf +0 -0
  55. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/004_comments.expected.cf +0 -0
  56. {cfengine-0.11.2 → cfengine-0.12.0}/tests/format/004_comments.input.cf +0 -0
  57. {cfengine-0.11.2 → cfengine-0.12.0}/tests/run-format-tests.sh +0 -0
  58. {cfengine-0.11.2 → cfengine-0.12.0}/tests/run-shell-tests.sh +0 -0
  59. {cfengine-0.11.2 → cfengine-0.12.0}/tests/shell/001-help.sh +0 -0
  60. {cfengine-0.11.2 → cfengine-0.12.0}/tests/shell/002-version.sh +0 -0
  61. {cfengine-0.11.2 → cfengine-0.12.0}/tests/shell/003-format.sh +0 -0
  62. {cfengine-0.11.2 → cfengine-0.12.0}/tests/test_deps.py +0 -0
  63. {cfengine-0.11.2 → cfengine-0.12.0}/tests/test_paths.py +0 -0
  64. {cfengine-0.11.2 → cfengine-0.12.0}/tests/test_utils.py +0 -0
  65. {cfengine-0.11.2 → cfengine-0.12.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfengine
3
- Version: 0.11.2
3
+ Version: 0.12.0
4
4
  Summary: Human-oriented CLI for interacting with 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.11.2
3
+ Version: 0.12.0
4
4
  Summary: Human-oriented CLI for interacting with CFEngine tools
5
5
  License: GNU GENERAL PUBLIC LICENSE
6
6
  Version 3, 29 June 2007
@@ -30,6 +30,7 @@ src/cfengine_cli/format.py
30
30
  src/cfengine_cli/lint.py
31
31
  src/cfengine_cli/main.py
32
32
  src/cfengine_cli/paths.py
33
+ src/cfengine_cli/policy_language.py
33
34
  src/cfengine_cli/profile.py
34
35
  src/cfengine_cli/shell.py
35
36
  src/cfengine_cli/utils.py
@@ -4,7 +4,7 @@ import re
4
4
  import json
5
5
  from cfengine_cli.profile import profile_cfengine, generate_callstack
6
6
  from cfengine_cli.dev import dispatch_dev_subcommand
7
- from cfengine_cli.lint import lint_single_arg, lint_folder
7
+ from cfengine_cli.lint import lint_folder, lint_single_arg
8
8
  from cfengine_cli.shell import user_command
9
9
  from cfengine_cli.paths import bin
10
10
  from cfengine_cli.version import cfengine_cli_version_string
@@ -94,21 +94,20 @@ def format(names, line_length) -> int:
94
94
  return 0
95
95
 
96
96
 
97
- def _lint(files) -> int:
98
-
97
+ def _lint(files, strict) -> int:
99
98
  if not files:
100
- return lint_folder(".")
99
+ return lint_folder(".", strict)
101
100
 
102
101
  errors = 0
103
102
 
104
103
  for file in files:
105
- errors += lint_single_arg(file)
104
+ errors += lint_single_arg(file, strict)
106
105
 
107
106
  return errors
108
107
 
109
108
 
110
- def lint(files) -> int:
111
- errors = _lint(files)
109
+ def lint(files, strict) -> int:
110
+ errors = _lint(files, strict)
112
111
  if errors == 0:
113
112
  print("Success, no errors found.")
114
113
  else:
@@ -409,7 +409,7 @@ def check_docs() -> int:
409
409
 
410
410
  Run by the command:
411
411
  cfengine dev lint-docs"""
412
- r = lint_folder(".")
412
+ r = lint_folder(".", strict=False)
413
413
  if r != 0:
414
414
  return r
415
415
  _process_markdown_code_blocks(
@@ -18,9 +18,12 @@ from tree_sitter import Language, Parser
18
18
  from cfbs.validate import validate_config
19
19
  from cfbs.cfbs_config import CFBSConfig
20
20
  from cfbs.utils import find
21
-
22
- DEPRECATED_PROMISE_TYPES = ["defaults", "guest_environments"]
23
- ALLOWED_BUNDLE_TYPES = ["agent", "common", "monitor", "server", "edit_line", "edit_xml"]
21
+ from cfengine_cli.policy_language import (
22
+ DEPRECATED_PROMISE_TYPES,
23
+ ALLOWED_BUNDLE_TYPES,
24
+ BUILTIN_PROMISE_TYPES,
25
+ BUILTIN_FUNCTIONS,
26
+ )
24
27
 
25
28
 
26
29
  def lint_cfbs_json(filename) -> int:
@@ -97,7 +100,7 @@ def _find_nodes(filename, lines, node):
97
100
  return matches
98
101
 
99
102
 
100
- def _single_node_checks(filename, lines, node):
103
+ def _single_node_checks(filename, lines, node, user_definition, strict):
101
104
  """Things which can be checked by only looking at one node,
102
105
  not needing to recurse into children."""
103
106
  line = node.range.start_point[0] + 1
@@ -117,6 +120,20 @@ def _single_node_checks(filename, lines, node):
117
120
  f"Deprecation: Promise type '{promise_type}' is deprecated at {filename}:{line}:{column}"
118
121
  )
119
122
  return 1
123
+ if strict and (
124
+ (
125
+ promise_type
126
+ not in BUILTIN_PROMISE_TYPES.union(
127
+ user_definition.get("custom_promise_types", set())
128
+ )
129
+ )
130
+ ):
131
+ _highlight_range(node, lines)
132
+ print(
133
+ f"Error: Undefined promise type '{promise_type}' at {filename}:{line}:{column}"
134
+ )
135
+ return 1
136
+
120
137
  if node.type == "bundle_block_name":
121
138
  if _text(node) != _text(node).lower():
122
139
  _highlight_range(node, lines)
@@ -138,10 +155,26 @@ def _single_node_checks(filename, lines, node):
138
155
  f"Error: Bundle type must be one of ({', '.join(ALLOWED_BUNDLE_TYPES)}), not '{_text(node)}' at {filename}:{line}:{column}"
139
156
  )
140
157
  return 1
158
+ if node.type == "calling_identifier":
159
+ if strict and (
160
+ _text(node)
161
+ not in BUILTIN_FUNCTIONS.union(
162
+ user_definition.get("all_bundle_names", set()),
163
+ user_definition.get("all_body_names", set()),
164
+ )
165
+ ):
166
+ _highlight_range(node, lines)
167
+ print(
168
+ f"Error: Call to unknown function / bundle / body '{_text(node)}' at at {filename}:{line}:{column}"
169
+ )
170
+ return 1
141
171
  return 0
142
172
 
143
173
 
144
- def _walk(filename, lines, node) -> int:
174
+ def _walk(filename, lines, node, user_definition=None, strict=True) -> int:
175
+ if user_definition is None:
176
+ user_definition = {}
177
+
145
178
  error_nodes = _find_node_type(filename, lines, node, "ERROR")
146
179
  if error_nodes:
147
180
  for node in error_nodes:
@@ -156,13 +189,44 @@ def _walk(filename, lines, node) -> int:
156
189
 
157
190
  errors = 0
158
191
  for node in _find_nodes(filename, lines, node):
159
- errors += _single_node_checks(filename, lines, node)
192
+ errors += _single_node_checks(filename, lines, node, user_definition, strict)
160
193
 
161
194
  return errors
162
195
 
163
196
 
197
+ def _parse_user_definition(filename, lines, root_node):
198
+ promise_blocks = _find_node_type(filename, lines, root_node, "promise_block_name")
199
+ bundle_blocks = _find_node_type(filename, lines, root_node, "bundle_block_name")
200
+ body_blocks = _find_node_type(filename, lines, root_node, "body_block_name")
201
+
202
+ return {
203
+ "custom_promise_types": {_text(x) for x in promise_blocks},
204
+ "all_bundle_names": {_text(x) for x in bundle_blocks},
205
+ "all_body_names": {_text(x) for x in body_blocks},
206
+ }
207
+
208
+
209
+ def _parse_policy_file(filename):
210
+ assert os.path.isfile(filename)
211
+ PY_LANGUAGE = Language(tscfengine.language())
212
+ parser = Parser(PY_LANGUAGE)
213
+
214
+ with open(filename, "rb") as f:
215
+ original_data = f.read()
216
+ tree = parser.parse(original_data)
217
+ lines = original_data.decode().split("\n")
218
+
219
+ return tree, lines, original_data
220
+
221
+
164
222
  def lint_policy_file(
165
- filename, original_filename=None, original_line=None, snippet=None, prefix=None
223
+ filename,
224
+ original_filename=None,
225
+ original_line=None,
226
+ snippet=None,
227
+ prefix=None,
228
+ user_definition=None,
229
+ strict=True,
166
230
  ):
167
231
  assert original_filename is None or type(original_filename) is str
168
232
  assert original_line is None or type(original_line) is int
@@ -177,14 +241,11 @@ def lint_policy_file(
177
241
  assert snippet and snippet > 0
178
242
  assert os.path.isfile(filename)
179
243
  assert filename.endswith((".cf", ".cfengine3", ".cf3", ".cf.sub"))
180
- PY_LANGUAGE = Language(tscfengine.language())
181
- parser = Parser(PY_LANGUAGE)
182
244
 
183
- with open(filename, "rb") as f:
184
- original_data = f.read()
185
- tree = parser.parse(original_data)
186
- lines = original_data.decode().split("\n")
245
+ if user_definition is None:
246
+ user_definition = {}
187
247
 
248
+ tree, lines, original_data = _parse_policy_file(filename)
188
249
  root_node = tree.root_node
189
250
  if root_node.type != "source_file":
190
251
  if snippet:
@@ -214,7 +275,7 @@ def lint_policy_file(
214
275
  else:
215
276
  print(f"Error: Empty policy file '{filename}'")
216
277
  errors += 1
217
- errors += _walk(filename, lines, root_node)
278
+ errors += _walk(filename, lines, root_node, user_definition, strict)
218
279
  if prefix:
219
280
  print(prefix, end="")
220
281
  if errors == 0:
@@ -235,8 +296,9 @@ def lint_policy_file(
235
296
  return errors
236
297
 
237
298
 
238
- def lint_folder(folder):
299
+ def lint_folder(folder, strict=True):
239
300
  errors = 0
301
+ policy_files = []
240
302
  while folder.endswith(("/.", "/")):
241
303
  folder = folder[0:-1]
242
304
  for filename in itertools.chain(
@@ -246,22 +308,44 @@ def lint_folder(folder):
246
308
  continue
247
309
  if filename.startswith(".") and not filename.startswith("./"):
248
310
  continue
249
- errors += lint_single_file(filename)
311
+
312
+ if filename.endswith((".cf", ".cfengine3", ".cf3", ".cf.sub")):
313
+ policy_files.append(filename)
314
+ else:
315
+ errors += lint_single_file(filename)
316
+
317
+ user_definition = {}
318
+
319
+ # First pass: Gather custom types
320
+ for filename in policy_files if strict else []:
321
+ tree, lines, _ = _parse_policy_file(filename)
322
+ if tree.root_node.type == "source_file":
323
+ for key, val in _parse_user_definition(
324
+ filename, lines, tree.root_node
325
+ ).items():
326
+ user_definition[key] = user_definition.get(key, set()).union(val)
327
+
328
+ # Second pass: lint all policy files
329
+ for filename in policy_files:
330
+ errors += lint_policy_file(
331
+ filename, user_definition=user_definition, strict=strict
332
+ )
250
333
  return errors
251
334
 
252
335
 
253
- def lint_single_file(file):
336
+ def lint_single_file(file, user_definition=None, strict=True):
254
337
  assert os.path.isfile(file)
255
338
  if file.endswith("/cfbs.json"):
256
339
  return lint_cfbs_json(file)
257
340
  if file.endswith(".json"):
258
341
  return lint_json(file)
259
342
  assert file.endswith(".cf")
260
- return lint_policy_file(file)
343
+ return lint_policy_file(file, user_definition=user_definition, strict=strict)
261
344
 
262
345
 
263
- def lint_single_arg(arg):
346
+ def lint_single_arg(arg, strict=True):
264
347
  if os.path.isdir(arg):
265
- return lint_folder(arg)
348
+ return lint_folder(arg, strict)
266
349
  assert os.path.isfile(arg)
267
- return lint_single_file(arg)
350
+
351
+ return lint_single_file(arg, strict)
@@ -52,6 +52,12 @@ def _get_arg_parser():
52
52
  "lint",
53
53
  help="Look for syntax errors and other simple mistakes",
54
54
  )
55
+ lnt.add_argument(
56
+ "--strict",
57
+ type=str,
58
+ default="yes",
59
+ help="Strict mode. Default=yes, checks for undefined promise types, bundles, bodies, functions",
60
+ )
55
61
  lnt.add_argument("files", nargs="*", help="Files to format")
56
62
  subp.add_parser(
57
63
  "report",
@@ -132,7 +138,7 @@ def run_command_with_args(args) -> int:
132
138
  if args.command == "format":
133
139
  return commands.format(args.files, args.line_length)
134
140
  if args.command == "lint":
135
- return commands.lint(args.files)
141
+ return commands.lint(args.files, (args.strict.lower() in ("y", "ye", "yes")))
136
142
  if args.command == "report":
137
143
  return commands.report()
138
144
  if args.command == "run":
@@ -0,0 +1,239 @@
1
+ # These constants are temporary and may change in the future
2
+ # TODO: Find a way to extract these from the generated "syntax-definition"-json file
3
+
4
+ DEPRECATED_PROMISE_TYPES = ["defaults", "guest_environments"]
5
+ ALLOWED_BUNDLE_TYPES = ["agent", "common", "monitor", "server", "edit_line", "edit_xml"]
6
+ BUILTIN_PROMISE_TYPES = {
7
+ "access",
8
+ "build_xpath",
9
+ "classes",
10
+ "commands",
11
+ "databases",
12
+ "defaults",
13
+ "delete_attribute",
14
+ "delete_lines",
15
+ "delete_text",
16
+ "delete_tree",
17
+ "field_edits",
18
+ "files",
19
+ "guest_environments",
20
+ "insert_lines",
21
+ "insert_text",
22
+ "insert_tree",
23
+ "measurements",
24
+ "meta",
25
+ "methods",
26
+ "packages",
27
+ "processes",
28
+ "replace_patterns",
29
+ "reports",
30
+ "roles",
31
+ "services",
32
+ "set_attribute",
33
+ "set_text",
34
+ "storage",
35
+ "users",
36
+ "vars",
37
+ }
38
+ BUILTIN_FUNCTIONS = {
39
+ "accessedbefore",
40
+ "accumulated",
41
+ "ago",
42
+ "and",
43
+ "basename",
44
+ "bundlesmatching",
45
+ "bundlestate",
46
+ "callstack_callers",
47
+ "callstack_promisers",
48
+ "canonify",
49
+ "canonifyuniquely",
50
+ "cf_version_after",
51
+ "cf_version_at",
52
+ "cf_version_before",
53
+ "cf_version_between",
54
+ "cf_version_maximum",
55
+ "cf_version_minimum",
56
+ "changedbefore",
57
+ "classesmatching",
58
+ "classfiltercsv",
59
+ "classfilterdata",
60
+ "classify",
61
+ "classmatch",
62
+ "concat",
63
+ "countclassesmatching",
64
+ "countlinesmatching",
65
+ "data_expand",
66
+ "data_readstringarray",
67
+ "data_readstringarrayidx",
68
+ "data_regextract",
69
+ "data_sysctlvalues",
70
+ "datastate",
71
+ "difference",
72
+ "dirname",
73
+ "diskfree",
74
+ "escape",
75
+ "eval",
76
+ "every",
77
+ "execresult",
78
+ "execresult_as_data",
79
+ "expandrange",
80
+ "file_hash",
81
+ "fileexists",
82
+ "filesexist",
83
+ "filesize",
84
+ "filestat",
85
+ "filter",
86
+ "findfiles",
87
+ "findfiles_up",
88
+ "findlocalgroups",
89
+ "findlocalusers",
90
+ "findprocesses",
91
+ "format",
92
+ "getacls",
93
+ "getbundlemetatags",
94
+ "getclassmetatags",
95
+ "getenv",
96
+ "getfields",
97
+ "getgid",
98
+ "getgroupinfo",
99
+ "getgroups",
100
+ "getindices",
101
+ "getuid",
102
+ "getuserinfo",
103
+ "getusers",
104
+ "getvalues",
105
+ "getvariablemetatags",
106
+ "grep",
107
+ "groupexists",
108
+ "hash",
109
+ "hash_to_int",
110
+ "hashmatch",
111
+ "host2ip",
112
+ "hostinnetgroup",
113
+ "hostrange",
114
+ "hostsseen",
115
+ "hostswithclass",
116
+ "hostswithgroup",
117
+ "hubknowledge",
118
+ "ifelse",
119
+ "int",
120
+ "intersection",
121
+ "ip2host",
122
+ "iprange",
123
+ "irange",
124
+ "is_type",
125
+ "isconnectable",
126
+ "isdir",
127
+ "isexecutable",
128
+ "isgreaterthan",
129
+ "isipinsubnet",
130
+ "islessthan",
131
+ "islink",
132
+ "isnewerthan",
133
+ "isnewerthantime",
134
+ "isplain",
135
+ "isreadable",
136
+ "isvariable",
137
+ "join",
138
+ "lastnode",
139
+ "laterthan",
140
+ "ldaparray",
141
+ "ldaplist",
142
+ "ldapvalue",
143
+ "length",
144
+ "lsdir",
145
+ "makerule",
146
+ "maparray",
147
+ "mapdata",
148
+ "maplist",
149
+ "max",
150
+ "mean",
151
+ "mergedata",
152
+ "min",
153
+ "network_connections",
154
+ "none",
155
+ "not",
156
+ "now",
157
+ "nth",
158
+ "on",
159
+ "or",
160
+ "packagesmatching",
161
+ "packageupdatesmatching",
162
+ "parseintarray",
163
+ "parsejson",
164
+ "parserealarray",
165
+ "parsestringarray",
166
+ "parsestringarrayidx",
167
+ "parseyaml",
168
+ "peerleader",
169
+ "peerleaders",
170
+ "peers",
171
+ "processexists",
172
+ "product",
173
+ "randomint",
174
+ "read_module_protocol",
175
+ "readcsv",
176
+ "readdata",
177
+ "readenvfile",
178
+ "readfile",
179
+ "readintarray",
180
+ "readintlist",
181
+ "readjson",
182
+ "readrealarray",
183
+ "readreallist",
184
+ "readstringarray",
185
+ "readstringarrayidx",
186
+ "readstringlist",
187
+ "readtcp",
188
+ "readyaml",
189
+ "regarray",
190
+ "regcmp",
191
+ "regex_replace",
192
+ "regextract",
193
+ "registryvalue",
194
+ "regldap",
195
+ "regline",
196
+ "reglist",
197
+ "remoteclassesmatching",
198
+ "remotescalar",
199
+ "returnszero",
200
+ "reverse",
201
+ "rrange",
202
+ "search_up",
203
+ "selectservers",
204
+ "shuffle",
205
+ "some",
206
+ "sort",
207
+ "splayclass",
208
+ "splitstring",
209
+ "storejson",
210
+ "strcmp",
211
+ "strftime",
212
+ "string",
213
+ "string_downcase",
214
+ "string_head",
215
+ "string_length",
216
+ "string_mustache",
217
+ "string_replace",
218
+ "string_reverse",
219
+ "string_split",
220
+ "string_tail",
221
+ "string_trim",
222
+ "string_upcase",
223
+ "sublist",
224
+ "sum",
225
+ "sysctlvalue",
226
+ "translatepath",
227
+ "type",
228
+ "unique",
229
+ "url_get",
230
+ "usemodule",
231
+ "userexists",
232
+ "useringroup",
233
+ "validdata",
234
+ "validjson",
235
+ "variablesmatching",
236
+ "variablesmatching_as_data",
237
+ "variance",
238
+ "version_compare",
239
+ }
@@ -329,7 +329,7 @@ wheels = [
329
329
 
330
330
  [[package]]
331
331
  name = "requests"
332
- version = "2.32.5"
332
+ version = "2.33.0"
333
333
  source = { registry = "https://pypi.org/simple" }
334
334
  dependencies = [
335
335
  { name = "certifi" },
@@ -337,9 +337,9 @@ dependencies = [
337
337
  { name = "idna" },
338
338
  { name = "urllib3" },
339
339
  ]
340
- sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
340
+ sdist = { url = "https://files.pythonhosted.org/packages/34/64/8860370b167a9721e8956ae116825caff829224fbca0ca6e7bf8ddef8430/requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652", size = 134232, upload-time = "2026-03-25T15:10:41.586Z" }
341
341
  wheels = [
342
- { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
342
+ { url = "https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b", size = 65017, upload-time = "2026-03-25T15:10:40.382Z" },
343
343
  ]
344
344
 
345
345
  [[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
File without changes
File without changes