cyberark-tpc-plugin-parser 0.4.2__tar.gz → 0.4.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 (28) hide show
  1. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/PKG-INFO +8 -4
  2. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/README.md +5 -3
  3. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/cyberark_tpc_plugin_parser.egg-info/PKG-INFO +8 -4
  4. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/cyberark_tpc_plugin_parser.egg-info/SOURCES.txt +1 -0
  5. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/pyproject.toml +12 -1
  6. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tests/test_lexer.py +29 -5
  7. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tests/test_parser.py +25 -3
  8. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/lexer.py +2 -6
  9. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/cpm_parameter_validation.py +1 -1
  10. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/utilities/regex.py +1 -1
  11. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/parser.py +6 -14
  12. cyberark_tpc_plugin_parser-0.4.4/tpc_plugin_parser/py.typed +0 -0
  13. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/LICENSE +0 -0
  14. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/cyberark_tpc_plugin_parser.egg-info/dependency_links.txt +0 -0
  15. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/cyberark_tpc_plugin_parser.egg-info/top_level.txt +0 -0
  16. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/setup.cfg +0 -0
  17. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/__init__.py +0 -0
  18. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/__init__.py +0 -0
  19. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/__init__.py +0 -0
  20. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/assignment.py +0 -0
  21. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/comment.py +0 -0
  22. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/fail_state.py +0 -0
  23. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/parse_error.py +0 -0
  24. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/section_header.py +0 -0
  25. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/tokens/transition.py +0 -0
  26. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/utilities/__init__.py +0 -0
  27. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/utilities/token_name.py +0 -0
  28. {cyberark_tpc_plugin_parser-0.4.2 → cyberark_tpc_plugin_parser-0.4.4}/tpc_plugin_parser/lexer/utilities/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cyberark-tpc-plugin-parser
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A package to help parse CyberArk TPC plugin prompts and process files.
5
5
  Author-email: Peter McDonald <git@petermcdonald.co.uk>
6
6
  License: MIT License
@@ -29,6 +29,7 @@ Project-URL: homepage, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser
29
29
  Project-URL: repository, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser.git
30
30
  Project-URL: issues, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser/issues
31
31
  Keywords: cyberark,parser,tpc
32
+ Classifier: Development Status :: 5 - Production/Stable
32
33
  Classifier: Intended Audience :: Developers
33
34
  Classifier: Programming Language :: Python
34
35
  Classifier: Programming Language :: Python :: 3.12
@@ -36,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.13
36
37
  Classifier: Programming Language :: Python :: 3.14
37
38
  Classifier: Programming Language :: Python :: 3.15
38
39
  Classifier: Programming Language :: Python :: 3.16
40
+ Classifier: Topic :: Security
39
41
  Classifier: Topic :: Software Development :: Testing
40
42
  Classifier: Typing :: Typed
41
43
  Requires-Python: >=3.12
@@ -73,7 +75,9 @@ with open("/path/to/files/process.ini") as process_fh:
73
75
  with open("/path/to/files/prompts.ini") as prompts_fh:
74
76
  prompts_content: str = prompts_fh.read()
75
77
 
76
- parser: Parser = Parser(process_file=process_content, prompts_file=prompts_content)
77
- process_file_tokens = parser.process_file
78
- prompt_file_tokens = parser.prompts_file
78
+ process_parser = Parser(file_contents=process_content)
79
+ process_file_tokens = process_parser.parsed_file
80
+
81
+ prompts_parser = Parser(file_contents=prompts_content)
82
+ prompt_file_tokens = prompts_parser.parsed_file
79
83
  ```
@@ -28,7 +28,9 @@ with open("/path/to/files/process.ini") as process_fh:
28
28
  with open("/path/to/files/prompts.ini") as prompts_fh:
29
29
  prompts_content: str = prompts_fh.read()
30
30
 
31
- parser: Parser = Parser(process_file=process_content, prompts_file=prompts_content)
32
- process_file_tokens = parser.process_file
33
- prompt_file_tokens = parser.prompts_file
31
+ process_parser = Parser(file_contents=process_content)
32
+ process_file_tokens = process_parser.parsed_file
33
+
34
+ prompts_parser = Parser(file_contents=prompts_content)
35
+ prompt_file_tokens = prompts_parser.parsed_file
34
36
  ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cyberark-tpc-plugin-parser
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A package to help parse CyberArk TPC plugin prompts and process files.
5
5
  Author-email: Peter McDonald <git@petermcdonald.co.uk>
6
6
  License: MIT License
@@ -29,6 +29,7 @@ Project-URL: homepage, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser
29
29
  Project-URL: repository, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser.git
30
30
  Project-URL: issues, https://github.com/petermcd/CyberArk-TPC-Plugin-Parser/issues
31
31
  Keywords: cyberark,parser,tpc
32
+ Classifier: Development Status :: 5 - Production/Stable
32
33
  Classifier: Intended Audience :: Developers
33
34
  Classifier: Programming Language :: Python
34
35
  Classifier: Programming Language :: Python :: 3.12
@@ -36,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.13
36
37
  Classifier: Programming Language :: Python :: 3.14
37
38
  Classifier: Programming Language :: Python :: 3.15
38
39
  Classifier: Programming Language :: Python :: 3.16
40
+ Classifier: Topic :: Security
39
41
  Classifier: Topic :: Software Development :: Testing
40
42
  Classifier: Typing :: Typed
41
43
  Requires-Python: >=3.12
@@ -73,7 +75,9 @@ with open("/path/to/files/process.ini") as process_fh:
73
75
  with open("/path/to/files/prompts.ini") as prompts_fh:
74
76
  prompts_content: str = prompts_fh.read()
75
77
 
76
- parser: Parser = Parser(process_file=process_content, prompts_file=prompts_content)
77
- process_file_tokens = parser.process_file
78
- prompt_file_tokens = parser.prompts_file
78
+ process_parser = Parser(file_contents=process_content)
79
+ process_file_tokens = process_parser.parsed_file
80
+
81
+ prompts_parser = Parser(file_contents=prompts_content)
82
+ prompt_file_tokens = prompts_parser.parsed_file
79
83
  ```
@@ -9,6 +9,7 @@ tests/test_lexer.py
9
9
  tests/test_parser.py
10
10
  tpc_plugin_parser/__init__.py
11
11
  tpc_plugin_parser/parser.py
12
+ tpc_plugin_parser/py.typed
12
13
  tpc_plugin_parser/lexer/__init__.py
13
14
  tpc_plugin_parser/lexer/lexer.py
14
15
  tpc_plugin_parser/lexer/tokens/__init__.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cyberark-tpc-plugin-parser"
3
- version = "0.4.2"
3
+ version = "0.4.4"
4
4
  description = "A package to help parse CyberArk TPC plugin prompts and process files."
5
5
  keywords = ["cyberark", "parser", "tpc"]
6
6
  authors = [{ name = "Peter McDonald", email = "git@petermcdonald.co.uk"}]
@@ -9,6 +9,7 @@ license = { file = "LICENSE" }
9
9
  requires-python = ">=3.12"
10
10
 
11
11
  classifiers = [
12
+ "Development Status :: 5 - Production/Stable",
12
13
  "Intended Audience :: Developers",
13
14
  "Programming Language :: Python",
14
15
  "Programming Language :: Python :: 3.12",
@@ -16,12 +17,17 @@ classifiers = [
16
17
  "Programming Language :: Python :: 3.14",
17
18
  "Programming Language :: Python :: 3.15",
18
19
  "Programming Language :: Python :: 3.16",
20
+ "Topic :: Security",
19
21
  "Topic :: Software Development :: Testing",
20
22
  "Typing :: Typed",
21
23
  ]
22
24
 
23
25
  dependencies = []
24
26
 
27
+ [build-system]
28
+ requires = ["setuptools>=84", "wheel"]
29
+ build-backend = "setuptools.build_meta"
30
+
25
31
  [project.urls]
26
32
  homepage = "https://github.com/petermcd/CyberArk-TPC-Plugin-Parser"
27
33
  repository = "https://github.com/petermcd/CyberArk-TPC-Plugin-Parser.git"
@@ -33,6 +39,11 @@ dev = [
33
39
  "pytest>=9.1.1",
34
40
  "pytest-cov>=7.1.0",
35
41
  ]
42
+ lint = [
43
+ "ruff>=0.16.8",
44
+ "troml>=0.4.1",
45
+ "ty>=0.0.82",
46
+ ]
36
47
 
37
48
  [tool.pytest.ini_options]
38
49
  addopts = "--cov=tpc_plugin_parser --cov-report term-missing --cov-report xml:coverage.xml"
@@ -36,6 +36,21 @@ class TestLexer:
36
36
  ),
37
37
  ],
38
38
  ),
39
+ (
40
+ "password, source=FILE",
41
+ [
42
+ (
43
+ TokenName.CPM_PARAMETER_VALIDATION,
44
+ CPMParameterValidation(
45
+ line_number=1,
46
+ name="password",
47
+ source="FILE",
48
+ mandatory="no",
49
+ allow_characters=None,
50
+ ),
51
+ ),
52
+ ],
53
+ ),
39
54
  (
40
55
  "TestVar",
41
56
  [
@@ -116,6 +131,20 @@ class TestLexer:
116
131
  ),
117
132
  ],
118
133
  ),
134
+ (
135
+ "standard=FAIL(' This is a standard fail state', 1234 )",
136
+ [
137
+ (
138
+ TokenName.FAIL_STATE,
139
+ FailState(
140
+ name="standard",
141
+ line_number=1,
142
+ message="' This is a standard fail state'",
143
+ code=1234,
144
+ ),
145
+ ),
146
+ ],
147
+ ),
119
148
  (
120
149
  "standard = FAIL ('This is a standard fail state, isn't it?', 2468)",
121
150
  [
@@ -270,8 +299,3 @@ class TestLexer:
270
299
  oversized = "x" * (_MAX_SOURCE_BYTES + 1)
271
300
  with pytest.raises(ValueError, match="maximum allowed size"):
272
301
  Lexer(source=oversized)
273
-
274
- def test_fail_state_code_out_of_range_raises(self) -> None:
275
- """Test that a fail-state error code outside 0–65535 raises ValueError."""
276
- with pytest.raises(ValueError, match="valid range"):
277
- _ = Lexer(source="state=fail(message, 65536)").tokens
@@ -2,6 +2,7 @@
2
2
 
3
3
  import pytest
4
4
 
5
+ from tpc_plugin_parser.lexer.tokens.assignment import Assignment
5
6
  from tpc_plugin_parser.parser import Parser
6
7
 
7
8
 
@@ -16,7 +17,7 @@ class TestParser:
16
17
  )
17
18
  def test_process(self, target_file: str) -> None:
18
19
  """
19
- Test to ensure that process file tokens parses ok.
20
+ Test to ensure that process file tokens parses OK.
20
21
 
21
22
  :param target_file: Path to the file.
22
23
  """
@@ -27,7 +28,7 @@ class TestParser:
27
28
 
28
29
  assert len(parser.parsed_file) == 6
29
30
  assert len(parser.parsed_file["default"]) == 6
30
- assert len(parser.parsed_file["states"]) == 8
31
+ assert len(parser.parsed_file["states"]) == 9
31
32
  assert len(parser.parsed_file["transitions"]) == 7
32
33
  assert len(parser.parsed_file["CPM Parameters Validation"]) == 5
33
34
  assert len(parser.parsed_file["parameters"]) == 5
@@ -41,7 +42,7 @@ class TestParser:
41
42
  )
42
43
  def test_prompts(self, target_file: str) -> None:
43
44
  """
44
- Test to ensure that prompts file tokens parses ok.
45
+ Test to ensure that prompts file tokens parses OK.
45
46
 
46
47
  :param target_file: Path to the file.
47
48
  """
@@ -53,3 +54,24 @@ class TestParser:
53
54
  assert len(parser.parsed_file) == 2
54
55
  assert len(parser.parsed_file["default"]) == 6
55
56
  assert len(parser.parsed_file["conditions"]) == 8
57
+
58
+ def test_duplicate_sections_are_merged(self) -> None:
59
+ """Test that a repeated section header adds to the earlier section rather than replacing it."""
60
+ parser = Parser(file_contents="[s]\na=1\n[t]\nb=2\n[s]\nc=3")
61
+
62
+ assert parser.parsed_file["s"] == [
63
+ Assignment(line_number=2, name="a", equals="=", assigned="1"),
64
+ Assignment(line_number=6, name="c", equals="=", assigned="3"),
65
+ ]
66
+ assert parser.parsed_file["t"] == [
67
+ Assignment(line_number=4, name="b", equals="=", assigned="2"),
68
+ ]
69
+
70
+ def test_explicit_default_section_does_not_overwrite_preamble(self) -> None:
71
+ """Test that an explicit [default] section is merged with lines preceding the first header."""
72
+ parser = Parser(file_contents="x=1\n[default]\ny=2")
73
+
74
+ assert parser.parsed_file["default"] == [
75
+ Assignment(line_number=1, name="x", equals="=", assigned="1"),
76
+ Assignment(line_number=3, name="y", equals="=", assigned="2"),
77
+ ]
@@ -160,7 +160,7 @@ class Lexer:
160
160
  CPMParameterValidation(
161
161
  name=str(match["name"]),
162
162
  source=str(match["source"]),
163
- mandatory=str(match["mandatory"]),
163
+ mandatory=str(match["mandatory"] or "no").strip(),
164
164
  allow_characters=allow_characters,
165
165
  line_number=line_number,
166
166
  ),
@@ -173,17 +173,13 @@ class Lexer:
173
173
 
174
174
  :param match: Regex match of the fail state.
175
175
  """
176
- code = int(match["code"])
177
- if not (0 <= code <= 65535):
178
- _log.warning("Fail-state error code %d at line %d", code, line_number)
179
- raise ValueError(f"Fail-state error code {code} is outside the valid range 0–65535")
180
176
  self._tokens.append(
181
177
  (
182
178
  TokenName.FAIL_STATE,
183
179
  FailState(
184
180
  name=str(match["name"]).strip(),
185
181
  message=str(match["message"]).strip(),
186
- code=code,
182
+ code=int(match["code"]),
187
183
  line_number=line_number,
188
184
  ),
189
185
  )
@@ -12,7 +12,7 @@ class CPMParameterValidation:
12
12
  line_number: int
13
13
  name: str
14
14
  source: str
15
- mandatory: str
15
+ mandatory: str = "no"
16
16
  allow_characters: str | None = None
17
17
  token_name: str = TokenName.CPM_PARAMETER_VALIDATION.value
18
18
 
@@ -7,6 +7,6 @@ CPM_PARAMETER_VALIDATION: str = (
7
7
  r"(?:\s*,\s*mandatory\s*=\s*(?P<mandatory>[^,]*))?"
8
8
  r"(?:\s*,\s*allowcharacters\s*=\s*(?P<allowcharacters>.*))?$"
9
9
  )
10
- FAIL_STATE: str = r"^\s*(?P<name>\w+)\s*=\s*fail\s*\(\s*(?P<message>.*),\s*(?P<code>[0-9]+)\)\s*$"
10
+ FAIL_STATE: str = r"^\s*(?P<name>\w+)\s*=\s*fail\s*\(\s*(?P<message>.*),\s*(?P<code>[0-9]+)\s*\)\s*$"
11
11
  SECTION_HEADER: str = r"^\s*\[(?P<name>\w+(?:\s+\w+)*)]\s*$"
12
12
  TRANSITION: str = r"^\s*(?P<current>\w+)\s*,\s*(?P<condition>\w+)\s*,\s*(?P<next>\w+)\s*$"
@@ -38,21 +38,13 @@ class Parser:
38
38
 
39
39
  :return: Result of processing the lexed file.
40
40
  """
41
- current_section_name: str = "default"
42
- section_entries: list[ALL_TOKEN_TYPES,] = []
43
- sorted_lex = {}
44
- for lexed_line in lexed_file.tokens:
45
- if lexed_line[0] == TokenName.SECTION_HEADER:
46
- sorted_lex[current_section_name] = section_entries
47
- if isinstance(lexed_line[1], SectionHeader):
48
- current_section_name = lexed_line[1].name
49
- else:
50
- # This should never be reached, this is here to satisfy typing.
51
- current_section_name = "UNKNOWN"
52
- section_entries = []
41
+ current: list[ALL_TOKEN_TYPES] = []
42
+ sorted_lex: dict[str, list[ALL_TOKEN_TYPES]] = {"default": current}
43
+ for token_name, token in lexed_file.tokens:
44
+ if token_name == TokenName.SECTION_HEADER and isinstance(token, SectionHeader):
45
+ current = sorted_lex.setdefault(token.name, [])
53
46
  continue
54
- section_entries.append(lexed_line[1])
55
- sorted_lex[current_section_name] = section_entries
47
+ current.append(token)
56
48
  return sorted_lex
57
49
 
58
50
  @property