Skip to content

Commit 2f3b3c4

Browse files
authored
Merge pull request #75 from olehermanse/refactoring2
Small fixes and refactorings / improvements
2 parents c586010 + 10fd76e commit 2f3b3c4

6 files changed

Lines changed: 60 additions & 79 deletions

File tree

src/cfengine_cli/deptool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ def deps_list(self, ref="master"):
260260
# currently only_deps is generator of space-separated deps,
261261
# i.e. each item can contain several items, like this:
262262
# list(only_deps) = ["lcov", "pthreads-w32 libgnurx"]
263-
# to "flattern" it we first join using spaces and then split on spaces
263+
# to "flatten" it we first join using spaces and then split on spaces
264264
# in the middle we also do some clean-ups
265265
only_deps = " ".join(only_deps).replace("libgcc ", "").split(" ")
266266
# now only_deps looks like this: ["lcov", "pthreads-w32", "libgnurx"]

src/cfengine_cli/dev.py

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,53 +25,42 @@ def _continue_prompt() -> bool:
2525
return answer in ("y", "yes")
2626

2727

28-
def _expect_repo(repo) -> bool:
28+
def _expect_repo(repo):
2929
cwd = os.getcwd()
3030
if cwd.endswith(repo):
31-
return True
31+
return
3232
print(f"Note: This command is intended to be run in the {repo} repo")
3333
print(f" https://github.com/cfengine/{repo}")
34-
answer = _continue_prompt()
35-
return answer
34+
if not _continue_prompt():
35+
raise UserError(f"Aborted (expected to be in {repo} repo)")
3636

3737

3838
def update_dependency_tables() -> int:
39-
answer = _expect_repo("buildscripts")
40-
if answer:
41-
return _update_dependency_tables()
42-
return 1
39+
_expect_repo("buildscripts")
40+
return _update_dependency_tables()
4341

4442

4543
def print_dependency_tables(args) -> int:
46-
versions = args.versions
47-
answer = _expect_repo("buildscripts")
48-
if answer:
49-
return print_release_dependency_tables(versions)
50-
return 1
44+
_expect_repo("buildscripts")
45+
return print_release_dependency_tables(args.versions)
5146

5247

5348
def format_docs(files) -> int:
54-
answer = _expect_repo("documentation")
55-
if answer:
56-
return update_docs(files)
57-
return 1
49+
_expect_repo("documentation")
50+
return update_docs(files)
5851

5952

6053
def lint_docs() -> int:
61-
answer = _expect_repo("documentation")
62-
if answer:
63-
return check_docs()
64-
return 1
54+
_expect_repo("documentation")
55+
return check_docs()
6556

6657

6758
def generate_release_information(
6859
omit_download=False, check=False, min_version=None
6960
) -> int:
70-
answer = _expect_repo("release-information")
71-
if answer:
72-
generate_release_information_command(omit_download, check, min_version)
73-
return 0
74-
return 1
61+
_expect_repo("release-information")
62+
generate_release_information_command(omit_download, check, min_version)
63+
return 0
7564

7665

7766
def dispatch_dev_subcommand(subcommand, args) -> int:

src/cfengine_cli/docs.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -346,20 +346,22 @@ def _process_markdown_code_blocks(
346346
os.remove(snippet_path)
347347

348348

349-
def _run_black(path):
350-
print(f"Formatting '{path}' with black...")
349+
def _run_formatter(tool, args, cwd, install_hint):
350+
print(f"Formatting with {tool}...")
351351
try:
352352
subprocess.run(
353-
["black", path],
353+
[tool, *args],
354354
capture_output=True,
355355
text=True,
356356
check=True,
357-
cwd=".",
357+
cwd=cwd,
358358
)
359359
except:
360-
raise UserError(
361-
"Encountered an error running black\nInstall: pipx install black"
362-
)
360+
raise UserError(f"Encountered an error running {tool}\nInstall: {install_hint}")
361+
362+
363+
def _run_black(path):
364+
_run_formatter("black", [path], ".", "pipx install black")
363365

364366

365367
def _run_prettier(path):
@@ -378,21 +380,15 @@ def _run_prettier(path):
378380
args.append("**.md")
379381
if not args:
380382
return
381-
try:
382-
# Warning: Beware of shell expansion if you try to run this in your terminal.
383-
# Wrong: prettier --write **.markdown **.md
384-
# Right: prettier --write '**.markdown' '**.md'
385-
subprocess.run(
386-
["prettier", "--embedded-language-formatting", "off", "--write", *args],
387-
capture_output=True,
388-
text=True,
389-
check=True,
390-
cwd=directory,
391-
)
392-
except:
393-
raise UserError(
394-
"Encountered an error running prettier\nInstall: npm install --global prettier"
395-
)
383+
# Warning: Beware of shell expansion if you try to run this in your terminal.
384+
# Wrong: prettier --write **.markdown **.md
385+
# Right: prettier --write '**.markdown' '**.md'
386+
_run_formatter(
387+
"prettier",
388+
["--embedded-language-formatting", "off", "--write", *args],
389+
directory,
390+
"npm install --global prettier",
391+
)
396392

397393

398394
def _update_docs_single_arg(path):

src/cfengine_cli/lint.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@
4040
from cfengine_cli.utils import UserError
4141

4242
LINT_EXTENSIONS = (".cf", ".json")
43+
DEFAULT_NAMESPACE = "default"
44+
VARS_TYPES = {
45+
"data",
46+
"ilist",
47+
"int",
48+
"real",
49+
"rlist",
50+
"slist",
51+
"string",
52+
}
53+
PROMISE_BLOCK_ATTRIBUTES = ("path", "interpreter")
54+
KNOWN_FAULTY_FUNCTION_DEFS = {"regex_replace"}
4355

4456

4557
@dataclass
@@ -130,7 +142,7 @@ class PolicyFile:
130142
reused when we iterate over it multiple times.
131143
132144
We store filename, raw data (bytes), array of lines, and syntax tree/nodes.
133-
This is a but of "duplication", but they are useful for printing nice
145+
This is a bit of "duplication", but they are useful for printing nice
134146
linting errors.
135147
136148
This is intended as a read-only view of the policy file, not to be used for
@@ -140,7 +152,7 @@ class PolicyFile:
140152
- Whether the file is empty
141153
- Whether the file has syntax errors
142154
- Whether the file uses macros (Macros can indicate we need to be less strict)
143-
- Things defined and referenced in the file (bundles, bodies, promise types, )
155+
- Things defined and referenced in the file (bundles, bodies, promise types)
144156
"""
145157

146158
def __init__(self, filename: str, snippet: Snippet | None = None):
@@ -179,7 +191,7 @@ class State:
179191
block_name: str | None = None
180192
promise_type: str | None = None # "vars" | "files" | "classes" | ... | None
181193
attribute_name: str | None = None # "if" | "string" | "slist" | ... | None
182-
namespace: str = "default" # "ns" | "default" | ... |
194+
namespace: str = DEFAULT_NAMESPACE # "ns" | "default" | ... |
183195
mode: Mode = Mode.NONE
184196
walking: bool = False
185197
strict: bool = True
@@ -244,7 +256,7 @@ def start_file(self, policy_file: PolicyFile):
244256
assert self.mode != Mode.NONE
245257

246258
self.policy_file = policy_file
247-
self.namespace = "default"
259+
self.namespace = DEFAULT_NAMESPACE
248260
self.walking = True
249261

250262
def end_file(self) -> None:
@@ -562,24 +574,14 @@ def _lint_node(
562574
return 1
563575
if state.promise_type == "vars" and node.type == "promise":
564576
attribute_nodes = [x for x in node.children if x.type == "attribute"]
565-
# Each vars promise must include exactly 1 of these attributes (a value):
566-
vars_types = {
567-
"data",
568-
"ilist",
569-
"int",
570-
"real",
571-
"rlist",
572-
"slist",
573-
"string",
574-
}
575577
# Attributes are children of a promise, and attribute names are children of attributes
576578
# Need to iterate inside to find the attribute name (data, ilist, int, etc.)
577579
value_nodes = []
578580
for attr in attribute_nodes:
579581
for child in attr.children:
580582
if child.type != "attribute_name":
581583
continue
582-
if _text(child) in vars_types:
584+
if _text(child) in VARS_TYPES:
583585
# Ignore the other attributes which are not values
584586
value_nodes.append(child)
585587

@@ -658,23 +660,17 @@ def _lint_node(
658660
if (
659661
state.block_keyword == "promise"
660662
and node.type == "attribute_name"
661-
and state.attribute_name
662-
not in (
663-
None,
664-
"path",
665-
"interpreter",
666-
)
663+
and state.attribute_name not in (None, *PROMISE_BLOCK_ATTRIBUTES)
667664
):
668665
_highlight_range(node, lines)
669666
print(
670667
f"Error: Invalid attribute name '{state.attribute_name}' in '{state.block_name}' custom promise type definition {location}"
671668
)
672669
return 1
673670
if node.type == "call":
674-
known_faulty_defs = {"regex_replace"}
675671
call, _, *args, _ = node.children # f ( a1 , a2 , a..N )
676672
call = _text(call)
677-
if call in known_faulty_defs:
673+
if call in KNOWN_FAULTY_FUNCTION_DEFS:
678674
return 0
679675

680676
args = list(filter(",".__ne__, iter(_text(x) for x in args)))
@@ -986,8 +982,8 @@ def _walk_callback(node: Node, callback: Callable[[Node], int]) -> int:
986982
def _parse_policy_file(filename: str) -> tuple[Tree, list[str], bytes]:
987983
"""Parse a policy file into a syntax tree using tree sitter.
988984
989-
This function is used by PolicyFile constructor, in most cases it will be
990-
to call Policyfile(filename) instead of this function."""
985+
This function is used by PolicyFile constructor, in most cases it is better
986+
to call PolicyFile(filename) instead of this function."""
991987
assert os.path.isfile(filename)
992988
PY_LANGUAGE = Language(tscfengine.language())
993989
parser = Parser(PY_LANGUAGE)

src/cfengine_cli/main.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _get_arg_parser():
5959
default="yes",
6060
help="Strict mode. Default=yes, checks for undefined promise types, bundles, bodies, functions",
6161
)
62-
lnt.add_argument("files", nargs="*", help="Files to format")
62+
lnt.add_argument("files", nargs="*", help="Files to lint")
6363
subp.add_parser(
6464
"report",
6565
help="Run the agent and hub commands necessary to get new reporting data",
@@ -101,17 +101,17 @@ def _get_arg_parser():
101101

102102
parser.add_argument(
103103
"--omit-download",
104-
help="Use existing masterfiles instead of downloading in 'cfbs generate-release-information'",
104+
help="Use existing masterfiles instead of downloading in 'cfengine dev generate-release-information'",
105105
action="store_true",
106106
)
107107
parser.add_argument(
108108
"--check-against-git",
109-
help="Check whether masterfiles from cfengine.com and github.com match in 'cfbs generate-release-information'",
109+
help="Check whether masterfiles from cfengine.com and github.com match in 'cfengine dev generate-release-information'",
110110
action="store_true",
111111
)
112112
parser.add_argument(
113113
"--from",
114-
help="Specify minimum version in 'cfbs generate-release-information'",
114+
help="Specify minimum version in 'cfengine dev generate-release-information'",
115115
dest="minimum_version",
116116
)
117117

src/cfengine_cli/profile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def generate_callstack(data, stack_path):
106106
"Successfully generated callstack at '{}'".format(os.path.abspath(stack_path))
107107
)
108108
print(
109-
"Run './flamgraph {} > flamegraph.svg' to generate the flamegraph".format(
109+
"Run './flamegraph {} > flamegraph.svg' to generate the flamegraph".format(
110110
stack_path
111111
)
112112
)

0 commit comments

Comments
 (0)