approval-utilities 13.0.0__tar.gz → 14.1.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.

Potentially problematic release.


This version of approval-utilities might be problematic. Click here for more details.

Files changed (69) hide show
  1. {approval_utilities-13.0.0/approval_utilities.egg-info → approval_utilities-14.1.0}/PKG-INFO +1 -1
  2. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utils.py +18 -2
  3. {approval_utilities-13.0.0 → approval_utilities-14.1.0/approval_utilities.egg-info}/PKG-INFO +1 -1
  4. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities.egg-info/SOURCES.txt +4 -0
  5. approval_utilities-14.1.0/tests/test_build.py +33 -0
  6. approval_utilities-14.1.0/tests/test_compare_file_lists.py +25 -0
  7. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_fileapprover.py +19 -2
  8. approval_utilities-14.1.0/tests/test_find_stale_approved_files.py +132 -0
  9. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_inline_approvals.py +1 -1
  10. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_options.py +1 -1
  11. approval_utilities-14.1.0/tests/test_verify_argument_parser.py +16 -0
  12. approval_utilities-14.1.0/version.py +1 -0
  13. approval_utilities-13.0.0/version.py +0 -1
  14. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/LICENSE +0 -0
  15. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/MANIFEST.in +0 -0
  16. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/README.md +0 -0
  17. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/__init__.py +0 -0
  18. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/approvaltests/__init__.py +0 -0
  19. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/approvaltests/core/__init__.py +0 -0
  20. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/approvaltests/core/executable_command.py +0 -0
  21. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/approvaltests/core/verifiable.py +0 -0
  22. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/approvaltests/core/verify_parameters.py +0 -0
  23. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/list_utils.py +0 -0
  24. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/__init__.py +0 -0
  25. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/clipboard_utilities.py +0 -0
  26. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/deprecated.py +0 -0
  27. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/exceptions/__init__.py +0 -0
  28. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/exceptions/exception_collector.py +0 -0
  29. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/exceptions/exception_utils.py +0 -0
  30. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/exceptions/multiple_exceptions.py +0 -0
  31. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/logger/__init__.py +0 -0
  32. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/logger/logging_instance.py +0 -0
  33. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/logger/simple_logger.py +0 -0
  34. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/map_reduce.py +0 -0
  35. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/markdown_table.py +0 -0
  36. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/multiline_string_utils.py +0 -0
  37. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/os_utilities.py +0 -0
  38. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/persistence/__init__.py +0 -0
  39. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/persistence/loader.py +0 -0
  40. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/persistence/saver.py +0 -0
  41. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/stack_frame_utilities.py +0 -0
  42. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/string_wrapper.py +0 -0
  43. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/time_utilities.py +0 -0
  44. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities/utilities/wrapper.py +0 -0
  45. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities.egg-info/dependency_links.txt +0 -0
  46. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/approval_utilities.egg-info/top_level.txt +0 -0
  47. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/requirements.prod.extras.txt +0 -0
  48. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/requirements.prod.required.txt +0 -0
  49. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/requirements.prod.txt +0 -0
  50. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/setup.cfg +0 -0
  51. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/setup.py +0 -0
  52. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/setup_utils.py +0 -0
  53. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_asserts.py +0 -0
  54. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_combinations.py +0 -0
  55. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_custom_printers.py +0 -0
  56. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_example_numpy.py +0 -0
  57. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_exception_utils.py +0 -0
  58. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_list.py +0 -0
  59. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_multiline_string_utils.py +0 -0
  60. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_namer.py +0 -0
  61. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_pairwise_combinations.py +0 -0
  62. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_parse_inputs.py +0 -0
  63. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_python_patterns.py +0 -0
  64. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_scenarios.py +0 -0
  65. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_simple_logger.py +0 -0
  66. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_split_code.py +0 -0
  67. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_verify.py +0 -0
  68. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_verify_all.py +0 -0
  69. {approval_utilities-13.0.0 → approval_utilities-14.1.0}/tests/test_writer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: approval_utilities
3
- Version: 13.0.0
3
+ Version: 14.1.0
4
4
  Summary: Utilities for your production code that work well with approvaltests
5
5
  Home-page: https://github.com/approvals/ApprovalTests.Python
6
6
  Author: ApprovalTests Contributors
@@ -1,8 +1,11 @@
1
1
  import inspect
2
2
  import json
3
3
  import os
4
+
4
5
  from copy import deepcopy
5
6
 
7
+ from typing import Callable, Dict, TypeVar
8
+
6
9
 
7
10
  def get_adjacent_file(name: str) -> str:
8
11
  calling_file = inspect.stack(1)[1][1]
@@ -53,12 +56,17 @@ def is_windows_os() -> bool:
53
56
 
54
57
 
55
58
  def create_empty_file(file_path: str) -> None:
56
- import empty_files.empty_files
59
+ try:
60
+ import empty_files.empty_files
57
61
 
58
- empty_files.empty_files.create_empty_file(file_path)
62
+ empty_files.empty_files.create_empty_file(file_path)
63
+ except ImportError as e:
64
+ print("Error importing empty_files", e)
65
+ raise
59
66
 
60
67
 
61
68
  def ensure_file_exists(approved_path: str) -> None:
69
+ print("approved_path check", approved_path)
62
70
  if not os.path.isfile(approved_path):
63
71
  create_empty_file(approved_path)
64
72
 
@@ -76,3 +84,11 @@ def print_grid(width, height, cell_print_func):
76
84
  result += cell_print_func(x, y)
77
85
  result += "\n"
78
86
  return result
87
+
88
+
89
+ _V = TypeVar("_V")
90
+ _K = TypeVar("_K")
91
+
92
+
93
+ def filter_values(filter: Callable[[_V], bool], a_dict: Dict[_K, _V]) -> Dict[_K, _V]:
94
+ return {k: v for k, v in a_dict.items() if filter(v)}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: approval_utilities
3
- Version: 13.0.0
3
+ Version: 14.1.0
4
4
  Summary: Utilities for your production code that work well with approvaltests
5
5
  Home-page: https://github.com/approvals/ApprovalTests.Python
6
6
  Author: ApprovalTests Contributors
@@ -42,11 +42,14 @@ approval_utilities/utilities/persistence/__init__.py
42
42
  approval_utilities/utilities/persistence/loader.py
43
43
  approval_utilities/utilities/persistence/saver.py
44
44
  tests/test_asserts.py
45
+ tests/test_build.py
45
46
  tests/test_combinations.py
47
+ tests/test_compare_file_lists.py
46
48
  tests/test_custom_printers.py
47
49
  tests/test_example_numpy.py
48
50
  tests/test_exception_utils.py
49
51
  tests/test_fileapprover.py
52
+ tests/test_find_stale_approved_files.py
50
53
  tests/test_inline_approvals.py
51
54
  tests/test_list.py
52
55
  tests/test_multiline_string_utils.py
@@ -60,4 +63,5 @@ tests/test_simple_logger.py
60
63
  tests/test_split_code.py
61
64
  tests/test_verify.py
62
65
  tests/test_verify_all.py
66
+ tests/test_verify_argument_parser.py
63
67
  tests/test_writer.py
@@ -0,0 +1,33 @@
1
+ import os
2
+ import ast
3
+
4
+
5
+ def test_no_imports_from_build_directory():
6
+ # Make sure no file imports from build
7
+ root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
8
+ for dirpath, dirnames, filenames in os.walk(root_dir):
9
+ # Exclude directories that start with '.'
10
+ dirnames[:] = [d for d in dirnames if not d.startswith(".") and d != "build"]
11
+ # also exclude venv
12
+ dirnames[:] = [d for d in dirnames if not d.startswith("venv")]
13
+ for filename in filenames:
14
+ # Skip files that start with '.' and non-Python files
15
+ if filename.startswith(".") or not filename.endswith(".py"):
16
+ continue
17
+ file_path = os.path.join(dirpath, filename)
18
+ with open(file_path, "r", encoding="utf-8") as file:
19
+ source = file.read()
20
+ try:
21
+ tree = ast.parse(source, filename=file_path)
22
+ except SyntaxError:
23
+ continue # Skip files with syntax errors
24
+ for node in ast.walk(tree):
25
+ if isinstance(node, ast.Import):
26
+ for alias in node.names:
27
+ if alias.name == "build" or alias.name.startswith("build."):
28
+ assert False, f"{file_path} imports 'build'"
29
+ elif isinstance(node, ast.ImportFrom):
30
+ if node.module == "build" or (
31
+ node.module and node.module.startswith("build.")
32
+ ):
33
+ assert False, f"{file_path} imports from 'build'"
@@ -0,0 +1,25 @@
1
+ def compare_log_and_file_system(log_file_names, fs_file_names):
2
+ return [file for file in fs_file_names if file not in log_file_names]
3
+
4
+
5
+ def test_returns_empty_list_for_two_empty_lists():
6
+ log_file_names = []
7
+ fs_file_names = []
8
+ assert compare_log_and_file_system(log_file_names, fs_file_names) == []
9
+
10
+
11
+ def test_returns_empty_list_for_identical_lists():
12
+ log_file_names = ["a", "b", "c"]
13
+ fs_file_names = ["a", "b", "c"]
14
+ assert compare_log_and_file_system(log_file_names, fs_file_names) == []
15
+
16
+
17
+ def test_returns_items_only_in_fs():
18
+ log_file_names = ["a", "b", "c"]
19
+ fs_file_names = ["a", "b", "c", "d", "e"]
20
+ assert compare_log_and_file_system(log_file_names, fs_file_names) == ["d", "e"]
21
+
22
+
23
+ # Future tests
24
+ # 1 - fs:[a,b,c], log:[a,b,c] => []
25
+ # 2 - fs:[a,b,c,d], log:[a,b,c] => [d]
@@ -8,6 +8,7 @@ from approvaltests.reporters.generic_diff_reporter_factory import (
8
8
  )
9
9
  from approvaltests.reporters.testing_reporter import ReporterForTesting
10
10
  from approvaltests.string_writer import StringWriter
11
+ from approvaltests.approved_file_log import ApprovedFilesLog
11
12
 
12
13
 
13
14
  class FileApproverTests(unittest.TestCase):
@@ -52,6 +53,22 @@ class FileApproverTests(unittest.TestCase):
52
53
  error = FileApprover.verify(namer, writer, reporter, Options().comparator)
53
54
  self.assertEqual(None, error)
54
55
 
56
+ def test_approved_file_is_logged(self):
57
+ name = approvals.get_default_namer().get_approved_filename()
58
+ log = ApprovedFilesLog.get_approved_files_log()
59
+ log_lines = log.read_text().split("\n")
60
+ name1 = name.replace(".txt", ".txt1")
61
+ name2 = name.replace(".txt", ".txt2")
55
62
 
56
- if __name__ == "__main__":
57
- unittest.main()
63
+ # check log is cleared
64
+ self.assertNotIn(name1, log_lines)
65
+ self.assertNotIn(name2, log_lines)
66
+
67
+ # touch approved file
68
+ verify("a", options=Options().for_file.with_extension(".txt1"))
69
+ verify("a", options=Options().for_file.with_extension(".txt2"))
70
+
71
+ # assert that the approved file is logged
72
+ log_lines = log.read_text().split("\n")
73
+ self.assertIn(name1, log_lines)
74
+ self.assertIn(name2, log_lines)
@@ -0,0 +1,132 @@
1
+ import os
2
+ import sys
3
+ import tempfile
4
+ import subprocess
5
+
6
+ from approvaltests import Options, verify_argument_parser
7
+ from approvaltests.utilities.logger.simple_logger_approvals import verify_simple_logger
8
+ from approval_utilities.utilities.logger.simple_logger import SimpleLogger
9
+ from tests.find_stale_approved_files import create_argument_parser
10
+ from approvaltests.scrubbers import create_regex_scrubber
11
+
12
+
13
+ # Create a temporary sandbox directory and log file
14
+ def create_sandbox(approved_files, log_entries, nested=False):
15
+ sandbox_dir = tempfile.TemporaryDirectory()
16
+ log_file_path = os.path.join(sandbox_dir.name, "approvedfiles.log")
17
+
18
+ # Create approved files in the sandbox
19
+ for file_name in approved_files:
20
+ if nested:
21
+ nested_dir = os.path.join(sandbox_dir.name, "nested")
22
+ os.makedirs(nested_dir, exist_ok=True)
23
+ open(os.path.join(nested_dir, file_name), "w").close()
24
+ else:
25
+ open(os.path.join(sandbox_dir.name, file_name), "w").close()
26
+
27
+ # Write the log entries to the log file
28
+ with open(log_file_path, "w") as log_file:
29
+ for entry in log_entries:
30
+ if nested:
31
+ log_file.write(os.path.join(sandbox_dir.name, "nested", entry) + "\n")
32
+ else:
33
+ log_file.write(os.path.join(sandbox_dir.name, entry) + "\n")
34
+
35
+ return sandbox_dir, log_file_path
36
+
37
+
38
+ # Execute the comparison script
39
+ def execute_script(directory, log_file):
40
+
41
+ script = "find_stale_approved_files.py"
42
+ dirname = os.path.dirname(__file__)
43
+ full_script = os.path.join(dirname, script)
44
+ print(f"Executing script: {full_script=}")
45
+ result = subprocess.run(
46
+ [sys.executable, full_script, directory, log_file],
47
+ capture_output=True,
48
+ text=True,
49
+ )
50
+ output = result.stdout
51
+ SimpleLogger.message(output)
52
+
53
+
54
+ def test_create_argument_parser():
55
+ verify_argument_parser(create_argument_parser())
56
+
57
+
58
+ def test_find_stale_approved_files():
59
+ scrubber = create_regex_scrubber(r".+(?=file\d\.)", "")
60
+ with verify_simple_logger(options=Options().with_scrubber(scrubber)):
61
+ # Test Scenario 1: All approved files are in the log
62
+ SimpleLogger.message("Test Scenario 1: All approved files are in the log")
63
+ approved_files_1 = [
64
+ "file1.approved.txt",
65
+ "file2.approved.doc",
66
+ "file3.approved.csv",
67
+ ]
68
+ log_entries_1 = approved_files_1
69
+ verify_files(approved_files_1, log_entries_1)
70
+
71
+ # Test Scenario 2: Approved files that are not in the log
72
+ SimpleLogger.message("Test Scenario 2: Approved files that are not in the log")
73
+ approved_files_2 = [
74
+ "file1.approved.txt",
75
+ "file2.approved.doc",
76
+ "file3.approved.csv",
77
+ "file4.approved.md",
78
+ ]
79
+ log_entries_2 = approved_files_2[
80
+ :-1
81
+ ] # Exclude 'file4.approved.md' from the log
82
+ verify_files(approved_files_2, log_entries_2)
83
+
84
+ # Test Scenario 3: Log contains files that are not in the directory
85
+ SimpleLogger.message(
86
+ "Test Scenario 3: Log contains files that are not in the directory"
87
+ )
88
+ approved_files_3 = ["file1.approved.txt", "file2.approved.doc"]
89
+ log_entries_3 = approved_files_3 + [
90
+ "file3.approved.csv"
91
+ ] # 'file3.approved.csv' is in the log but not in the directory
92
+ verify_files(approved_files_3, log_entries_3)
93
+
94
+ # Test Scenario 4: No approved files in the directory
95
+ SimpleLogger.message("Test Scenario 4: No approved files in the directory")
96
+ verify_files([], ["file1.approved.txt", "file2.approved.doc"])
97
+
98
+ # Test Scenario 5: Directory has files but none are in the log
99
+ SimpleLogger.message(
100
+ "Test Scenario 5: Directory has files but none are in the log"
101
+ )
102
+ verify_files(["file1.approved.txt", "file2.approved.doc"], [])
103
+
104
+ # Test Scenario 6: Nested folders with approved files
105
+ SimpleLogger.message("Test Scenario 6: Nested folders with approved files")
106
+ approved_files_6 = ["file1.approved.txt", "file2.approved.doc"]
107
+ verify_files(approved_files_6, approved_files_6, nested=True)
108
+
109
+ # Test Scenario 7: Files that do not match the naming convention
110
+ SimpleLogger.message(
111
+ "Test Scenario 7: Files that do not match the naming convention"
112
+ )
113
+ approved_files_7 = ["file1.txt", "file2.doc", "file3.csv"]
114
+ verify_files(approved_files_7, approved_files_7)
115
+
116
+ SimpleLogger.message(
117
+ "Test Scenario 8: Log contains files that are not in the directory"
118
+ )
119
+ approved_files = ["custom_name_1.txt"]
120
+ log_entries = approved_files + ["custom_name_2.txt"]
121
+ verify_files(approved_files, log_entries)
122
+
123
+
124
+ def verify_files(approved_files, log_entries, nested=False):
125
+ SimpleLogger.variable("Approved Files", approved_files)
126
+ SimpleLogger.variable("Log Entries", log_entries)
127
+
128
+ sandbox_dir, log_file_path = create_sandbox(
129
+ approved_files, log_entries, nested=nested
130
+ )
131
+ execute_script(sandbox_dir.name, log_file_path)
132
+ sandbox_dir.cleanup()
@@ -16,7 +16,7 @@ from approvaltests import (
16
16
  from approvaltests.inline.inline_options import InlineOptions
17
17
  from approvaltests.inline.parse_docstring import parse_docstring
18
18
  from approvaltests.reporters.report_quietly import ReportQuietly
19
- from build.lib.approvaltests.reporters.report_with_beyond_compare import (
19
+ from approvaltests.reporters.report_with_beyond_compare import (
20
20
  ReportWithPycharm,
21
21
  ReportWithBeyondCompare,
22
22
  )
@@ -8,7 +8,7 @@ from approvaltests import (
8
8
  combination_approvals,
9
9
  )
10
10
  from approvaltests.core.options import Options
11
- from approvaltests.mrjob import mrjob_approvals
11
+ from approvaltests.integrations.mrjob import mrjob_approvals
12
12
  from approvaltests.reporters import ReportByCreatingDiffFile, MultiReporter
13
13
  from approvaltests.reporters.report_with_beyond_compare import ReportWithPycharm
14
14
  from approvaltests.utilities import command_line_approvals
@@ -0,0 +1,16 @@
1
+ import argparse
2
+ import os
3
+
4
+ from approvaltests import verify_argument_parser
5
+ from tests.find_stale_approved_files import create_argument_parser
6
+
7
+
8
+ def test_argument_parser():
9
+ parser = argparse.ArgumentParser(
10
+ prog="my_program.py",
11
+ description="My Description",
12
+ )
13
+ parser.add_argument("1st_argument", help="1st argument help text")
14
+ parser.add_argument("--optional_argument", help="An Optional Argument help text")
15
+ parser.add_argument("long_argument", help=f"{'Very' * 100} Long message")
16
+ verify_argument_parser(parser)
@@ -0,0 +1 @@
1
+ version_number = "v14.1.0"
@@ -1 +0,0 @@
1
- version_number = "v13.0.0"