diff options
Diffstat (limited to '')
-rw-r--r-- | tests/lint_tests/lint_tutil.py | 6 | ||||
-rw-r--r-- | tests/test_fs_metadata.py | 115 | ||||
-rw-r--r-- | tests/test_install_rules.py | 2 | ||||
-rw-r--r-- | tests/test_parser.py | 25 | ||||
-rw-r--r-- | tests/test_style.py | 51 |
5 files changed, 144 insertions, 55 deletions
diff --git a/tests/lint_tests/lint_tutil.py b/tests/lint_tests/lint_tutil.py index 74e08db..c32ad3c 100644 --- a/tests/lint_tests/lint_tutil.py +++ b/tests/lint_tests/lint_tutil.py @@ -9,7 +9,7 @@ from debputy.linting.lint_util import ( LintStateImpl, LintState, ) -from debputy.lsp.style_prefs import StylePreferenceTable, EffectivePreference +from debputy.lsp.maint_prefs import MaintainerPreferenceTable, EffectivePreference from debputy.packages import DctrlParser from debputy.plugin.api.feature_set import PluginProvidedFeatureSet @@ -42,7 +42,7 @@ class LintWrapper: self.path = path self._dctrl_parser = dctrl_parser self.source_root: Optional[VirtualPathBase] = None - self.lint_style_preference_table = StylePreferenceTable({}, {}) + self.lint_maint_preference_table = MaintainerPreferenceTable({}, {}) self.effective_preference: Optional[EffectivePreference] = None def __call__(self, lines: List[str]) -> Optional[List["Diagnostic"]]: @@ -59,7 +59,7 @@ class LintWrapper: debian_dir = source_root.get("debian") if source_root is not None else None state = LintStateImpl( self._debputy_plugin_feature_set, - self.lint_style_preference_table, + self.lint_maint_preference_table, source_root, debian_dir, self.path, diff --git a/tests/test_fs_metadata.py b/tests/test_fs_metadata.py index 7dd3d55..3cbbb03 100644 --- a/tests/test_fs_metadata.py +++ b/tests/test_fs_metadata.py @@ -132,7 +132,9 @@ def test_mtime_clamp_and_builtin_dir_mode( verify_paths(intermediate_manifest, path_defs) -def test_transformations_create_symlink(manifest_parser_pkg_foo): +def test_transformations_create_symlink( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -178,7 +180,9 @@ def test_transformations_create_symlink(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformations_create_symlink_replace_success(manifest_parser_pkg_foo): +def test_transformations_create_symlink_replace_success( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -230,8 +234,10 @@ def test_transformations_create_symlink_replace_success(manifest_parser_pkg_foo) ], ) def test_transformations_create_symlink_replace_failure( - manifest_parser_pkg_foo, replacement_rule, reason -): + manifest_parser_pkg_foo: YAMLManifestParser, + replacement_rule: str, + reason: str, +) -> None: content = textwrap.dedent( f"""\ manifest-version: '0.1' @@ -257,14 +263,15 @@ def test_transformations_create_symlink_replace_failure( f"Refusing to replace ./usr/share/foo with a symlink; {reason} and the active" f" replacement-rule was {replacement_rule}. You can set the replacement-rule to" ' "discard-existing", if you are not interested in the contents of ./usr/share/foo. This error' - " was triggered by packages.foo.transformations[0].create-symlink <Search for: usr/share/foo>." + # Ideally, this would be reported for line 5. + " was triggered by packages.foo.transformations[0].create-symlink [Line 6 column 18]." ) assert e_info.value.args[0] == msg def test_transformations_create_symlink_replace_with_explicit_remove( - manifest_parser_pkg_foo, -): + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -299,8 +306,8 @@ def test_transformations_create_symlink_replace_with_explicit_remove( def test_transformations_create_symlink_replace_with_replacement_rule( - manifest_parser_pkg_foo, -): + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -335,7 +342,9 @@ def test_transformations_create_symlink_replace_with_replacement_rule( verify_paths(intermediate_manifest, expected_results) -def test_transformations_path_metadata(manifest_parser_pkg_foo): +def test_transformations_path_metadata( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -382,7 +391,9 @@ def test_transformations_path_metadata(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformations_directories(manifest_parser_pkg_foo): +def test_transformations_directories( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -453,7 +464,9 @@ def test_transformations_directories(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformation_remove(manifest_parser_pkg_foo): +def test_transformation_remove( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -489,7 +502,9 @@ def test_transformation_remove(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformation_remove_keep_empty(manifest_parser_pkg_foo): +def test_transformation_remove_keep_empty( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -529,7 +544,9 @@ def test_transformation_remove_keep_empty(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformation_remove_glob(manifest_parser_pkg_foo): +def test_transformation_remove_glob( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -581,7 +598,9 @@ def test_transformation_remove_glob(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformation_remove_no_match(manifest_parser_pkg_foo): +def test_transformation_remove_no_match( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -612,13 +631,15 @@ def test_transformation_remove_no_match(manifest_parser_pkg_foo): manifest.apply_to_binary_staging_directory("foo", fs_root, claim_mtime_to) expected = ( 'The match rule "./some/non-existing-path" in transformation' - ' "packages.foo.transformations[0].remove <Search for: some/non-existing-path>" did not match any paths. Either' + ' "packages.foo.transformations[0].remove [Line 5 column 18]" did not match any paths. Either' " the definition is redundant (and can be omitted) or the match rule is incorrect." ) assert expected == e_info.value.args[0] -def test_transformation_move_basic(manifest_parser_pkg_foo): +def test_transformation_move_basic( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -682,7 +703,9 @@ def test_transformation_move_basic(manifest_parser_pkg_foo): verify_paths(intermediate_manifest, expected_results) -def test_transformation_move_no_match(manifest_parser_pkg_foo): +def test_transformation_move_no_match( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: content = textwrap.dedent( """\ manifest-version: '0.1' @@ -715,13 +738,15 @@ def test_transformation_move_no_match(manifest_parser_pkg_foo): manifest.apply_to_binary_staging_directory("foo", fs_root, claim_mtime_to) expected = ( 'The match rule "./some/non-existing-path" in transformation' - ' "packages.foo.transformations[0].move <Search for: some/non-existing-path>" did not match any paths. Either' + ' "packages.foo.transformations[0].move [Line 6 column 12]" did not match any paths. Either' " the definition is redundant (and can be omitted) or the match rule is incorrect." ) assert expected == e_info.value.args[0] -def test_builtin_mode_normalization(manifest_parser_pkg_foo): +def test_builtin_mode_normalization_shell_scripts( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: manifest = manifest_parser_pkg_foo.build_manifest() claim_mtime_to = 255 sh_script_content = "#!/bin/sh" @@ -773,3 +798,53 @@ def test_builtin_mode_normalization(manifest_parser_pkg_foo): print(intermediate_manifest) verify_paths(intermediate_manifest, expected_results) + + +def test_builtin_mode_normalization( + manifest_parser_pkg_foo: YAMLManifestParser, +) -> None: + manifest = manifest_parser_pkg_foo.build_manifest() + claim_mtime_to = 255 + + paths = [ + virtual_path_def("usr/", mode=0o755, mtime=10, fs_path="/nowhere/usr"), + virtual_path_def( + "usr/share/", mode=0o755, mtime=10, fs_path="/nowhere/usr/share" + ), + virtual_path_def( + "usr/share/perl5/", mode=0o755, mtime=10, fs_path="/nowhere/usr/share/perl5" + ), + virtual_path_def( + "usr/share/perl5/Foo.pm", + # #1076346 + mode=0o444, + mtime=10, + fs_path="/nowhere/Foo.pm", + ), + virtual_path_def( + "usr/share/perl5/Bar.pm", + mode=0o755, + mtime=10, + fs_path="/nowhere/Bar.pm", + ), + ] + + fs_root = build_virtual_fs(paths, read_write_fs=True) + assert [p.name for p in manifest.all_packages] == ["foo"] + + expected_results = [ + ("usr/", Expected(mode=0o755, mtime=10)), + ("usr/share/", Expected(mode=0o755, mtime=10)), + ("usr/share/perl5/", Expected(mode=0o755, mtime=10)), + ("usr/share/perl5/Bar.pm", Expected(mode=0o644, mtime=10)), + ("usr/share/perl5/Foo.pm", Expected(mode=0o644, mtime=10)), + ] + assert [p.name for p in manifest.all_packages] == ["foo"] + + intermediate_manifest = manifest.apply_to_binary_staging_directory( + "foo", fs_root, claim_mtime_to + ) + + print(intermediate_manifest) + + verify_paths(intermediate_manifest, expected_results) diff --git a/tests/test_install_rules.py b/tests/test_install_rules.py index a361864..e94e8bc 100644 --- a/tests/test_install_rules.py +++ b/tests/test_install_rules.py @@ -620,7 +620,7 @@ def test_install_rules_no_matches(manifest_parser_pkg_foo) -> None: ) expected_msg = ( "There were no matches for build/private-arch-tool in /nowhere/debian/tmp, /nowhere" - " (definition: installations[0].install <Search for: build/private-arch-tool>)." + " (definition: installations[0].install [Line 5 column 6])." " Match rule: ./build/private-arch-tool (the exact path / no globbing)" ) assert e_info.value.message == expected_msg diff --git a/tests/test_parser.py b/tests/test_parser.py index 4aee024..1c84445 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -124,7 +124,10 @@ def test_parsing_variables_reserved(manifest_parser_pkg_foo, varname): with pytest.raises(ManifestParseException) as e_info: manifest_parser_pkg_foo.parse_manifest(fd=content) - msg = f'The variable "{varname}" is already reserved/defined. Error triggered by definitions.variables.{varname}.' + msg = ( + f'The variable "{varname}" is already reserved/defined.' + f" Error triggered by definitions.variables.{varname} [Line 4 column 4]." + ) assert normalize_doc_link(e_info.value.args[0]) == msg @@ -163,7 +166,7 @@ def test_parsing_variables_unused(manifest_parser_pkg_foo): msg = ( 'The variable "UNUSED" is unused. Either use it or remove it.' - " The variable was declared at definitions.variables.UNUSED." + " The variable was declared at definitions.variables.UNUSED [Line 4 column 4]." ) assert normalize_doc_link(e_info.value.args[0]) == msg @@ -181,7 +184,7 @@ def test_parsing_package_foo_empty(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) msg = ( - "The attribute packages.foo must be a non-empty mapping. Please see" + "The attribute packages.foo [Line 3 column 4] must be a non-empty mapping. Please see" " {{DEBPUTY_DOC_ROOT_DIR}}/MANIFEST-FORMAT.md#binary-package-rules for the documentation." ) assert normalize_doc_link(e_info.value.args[0]) == msg @@ -238,8 +241,8 @@ def test_create_symlinks_missing_path(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) msg = ( - "The following keys were required but not present at packages.foo.transformations[0].create-symlink: 'path'" - " (Documentation: " + "The following keys were required but not present at packages.foo.transformations[0].create-symlink" + " [Line 5 column 12]: 'path' (Documentation: " "{{DEBPUTY_DOC_ROOT_DIR}}/MANIFEST-FORMAT.md#create-symlinks-transformation-rule-create-symlink)" ) assert normalize_doc_link(e_info.value.args[0]) == msg @@ -263,7 +266,7 @@ def test_create_symlinks_unknown_replacement_rule(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) msg = ( - 'The attribute "packages.foo.transformations[0].create-symlink.replacement-rule <Search for: usr/share/foo>"' + 'The attribute "packages.foo.transformations[0].create-symlink.replacement-rule [Line 8 column 32]"' " did not have a valid structure/type: Value (golf) must be one of the following literal values:" ' "error-if-exists", "error-if-directory", "abort-on-non-empty-directory", "discard-existing"' ) @@ -286,8 +289,8 @@ def test_create_symlinks_missing_target(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) msg = ( - "The following keys were required but not present at packages.foo.transformations[0].create-symlink: 'target'" - " (Documentation: " + "The following keys were required but not present at packages.foo.transformations[0].create-symlink" + " [Line 5 column 12]: 'target' (Documentation: " "{{DEBPUTY_DOC_ROOT_DIR}}/MANIFEST-FORMAT.md#create-symlinks-transformation-rule-create-symlink)" ) assert normalize_doc_link(e_info.value.args[0]) == msg @@ -310,7 +313,7 @@ def test_create_symlinks_not_normalized_path(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) expected = ( - 'The path "../bar" provided in packages.foo.transformations[0].create-symlink.path <Search for: ../bar>' + 'The path "../bar" provided in packages.foo.transformations[0].create-symlink.path [Line 6 column 20]' ' should be relative to the root of the package and not use any ".." or "." segments.' ) assert e_info.value.args[0] == expected @@ -332,7 +335,7 @@ def test_unresolvable_subst_in_source_context(manifest_parser_pkg_foo): expected = ( "The variable {{PACKAGE}} is not available while processing installations[0].install.as" - " <Search for: foo.sh>." + " [Line 5 column 7]." ) assert e_info.value.args[0] == expected @@ -397,7 +400,7 @@ def test_yaml_octal_mode_int(manifest_parser_pkg_foo): manifest_parser_pkg_foo.parse_manifest(fd=content) msg = ( - 'The attribute "packages.foo.transformations[0].path-metadata.mode <Search for: usr/share/bar>" did not' + 'The attribute "packages.foo.transformations[0].path-metadata.mode [Line 7 column 20]" did not' " have a valid structure/type: The attribute must be a FileSystemMode (string)" ) diff --git a/tests/test_style.py b/tests/test_style.py index ef6ddc4..d3cfb14 100644 --- a/tests/test_style.py +++ b/tests/test_style.py @@ -4,9 +4,9 @@ import pytest from debian.deb822 import Deb822 from debputy.yaml.compat import CommentedMap -from debputy.lsp.style_prefs import ( - StylePreferenceTable, - determine_effective_style, +from debputy.lsp.maint_prefs import ( + MaintainerPreferenceTable, + determine_effective_preference, EffectivePreference, _WAS_DEFAULTS, ) @@ -14,7 +14,7 @@ from debputy.packages import SourcePackage def test_load_styles() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() assert "niels@thykier.net" in styles.maintainer_preferences nt_style = styles.maintainer_preferences["niels@thykier.net"] # Note this is data dependent; if it fails because the style changes, update the test @@ -32,7 +32,7 @@ def test_load_styles() -> None: def test_load_named_styles() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() assert "black" in styles.named_styles black_style = styles.named_styles["black"] # Note this is data dependent; if it fails because the style changes, update the test @@ -48,7 +48,7 @@ def test_load_named_styles() -> None: def test_compat_styles() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() # Data dependent; if it breaks, provide a stubbed style preference table assert "niels@thykier.net" in styles.maintainer_preferences @@ -71,30 +71,33 @@ def test_compat_styles() -> None: ) src = SourcePackage(fields) - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style == nt_pref + assert tool == "debputy reformat" fields["Uploaders"] = ( "Niels Thykier <niels@thykier.net>, Chris Hofstaedtler <zeha@debian.org>" ) src = SourcePackage(fields) - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style == nt_pref assert effective_style == zeha_pref + assert tool == "debputy reformat" fields["Uploaders"] = ( "Niels Thykier <niels@thykier.net>, Chris Hofstaedtler <zeha@debian.org>, Random Developer <random@example.org>" ) src = SourcePackage(fields) - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style is None + assert tool is None @pytest.mark.xfail def test_compat_styles_team_maint() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() fields = Deb822( { "Package": "foo", @@ -108,12 +111,13 @@ def test_compat_styles_team_maint() -> None: assert "random@example.org" not in styles.maintainer_preferences team_style = styles.maintainer_preferences["team@lists.debian.org"] assert team_style.is_packaging_team - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style == team_style.as_effective_pref() + assert tool is None def test_x_style() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() fields = Deb822( { "Package": "foo", @@ -125,12 +129,13 @@ def test_x_style() -> None: assert "random@example.org" not in styles.maintainer_preferences assert "black" in styles.named_styles black_style = styles.named_styles["black"] - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style == black_style + assert tool == "debputy reformat" def test_was_from_salsa_ci_style() -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() fields = Deb822( { "Package": "foo", @@ -139,20 +144,23 @@ def test_was_from_salsa_ci_style() -> None: ) src = SourcePackage(fields) assert "random@example.org" not in styles.maintainer_preferences - effective_style, _ = determine_effective_style(styles, src, None) + effective_style, tool, _ = determine_effective_preference(styles, src, None) assert effective_style is None + assert tool is None salsa_ci = CommentedMap( {"variables": CommentedMap({"SALSA_CI_DISABLE_WRAP_AND_SORT": "yes"})} ) - effective_style, _ = determine_effective_style(styles, src, salsa_ci) + effective_style, tool, _ = determine_effective_preference(styles, src, salsa_ci) assert effective_style is None + assert tool is None salsa_ci = CommentedMap( {"variables": CommentedMap({"SALSA_CI_DISABLE_WRAP_AND_SORT": "no"})} ) - effective_style, _ = determine_effective_style(styles, src, salsa_ci) + effective_style, tool, _ = determine_effective_preference(styles, src, salsa_ci) was_style = EffectivePreference(**_WAS_DEFAULTS) assert effective_style == was_style + assert tool == "wrap-and-sort" @pytest.mark.parametrize( @@ -197,9 +205,10 @@ def test_was_from_salsa_ci_style() -> None: ], ) def test_was_from_salsa_ci_style_args( - was_args: str, style_delta: Optional[Mapping[str, Any]] + was_args: str, + style_delta: Optional[Mapping[str, Any]], ) -> None: - styles = StylePreferenceTable.load_styles() + styles = MaintainerPreferenceTable.load_preferences() fields = Deb822( { "Package": "foo", @@ -218,12 +227,14 @@ def test_was_from_salsa_ci_style_args( ) } ) - effective_style, _ = determine_effective_style(styles, src, salsa_ci) + effective_style, tool, _ = determine_effective_preference(styles, src, salsa_ci) if style_delta is None: assert effective_style is None + assert tool is None else: was_style = EffectivePreference(**_WAS_DEFAULTS).replace( **style_delta, ) assert effective_style == was_style + assert tool == f"wrap-and-sort {was_args}".strip() |