daktari 0.0.330__tar.gz → 0.0.332__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 (81) hide show
  1. {daktari-0.0.330/daktari.egg-info → daktari-0.0.332}/PKG-INFO +2 -2
  2. {daktari-0.0.330 → daktari-0.0.332}/README.md +1 -1
  3. daktari-0.0.332/daktari/__init__.py +1 -0
  4. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/git.py +2 -1
  5. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/misc.py +11 -7
  6. daktari-0.0.332/daktari/checks/test_misc.py +53 -0
  7. daktari-0.0.332/daktari/test_git.py +55 -0
  8. {daktari-0.0.330 → daktari-0.0.332/daktari.egg-info}/PKG-INFO +2 -2
  9. {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/SOURCES.txt +1 -0
  10. {daktari-0.0.330 → daktari-0.0.332}/pyproject.toml +1 -1
  11. daktari-0.0.330/daktari/__init__.py +0 -1
  12. daktari-0.0.330/daktari/checks/test_misc.py +0 -18
  13. {daktari-0.0.330 → daktari-0.0.332}/LICENSE.txt +0 -0
  14. {daktari-0.0.330 → daktari-0.0.332}/MANIFEST.in +0 -0
  15. {daktari-0.0.330 → daktari-0.0.332}/daktari/__main__.py +0 -0
  16. {daktari-0.0.330 → daktari-0.0.332}/daktari/asdf.py +0 -0
  17. {daktari-0.0.330 → daktari-0.0.332}/daktari/check.py +0 -0
  18. {daktari-0.0.330 → daktari-0.0.332}/daktari/check_runner.py +0 -0
  19. {daktari-0.0.330 → daktari-0.0.332}/daktari/check_sorter.py +0 -0
  20. {daktari-0.0.330 → daktari-0.0.332}/daktari/check_utils.py +0 -0
  21. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/__init__.py +0 -0
  22. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/android.py +0 -0
  23. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/aws.py +0 -0
  24. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/certs.py +0 -0
  25. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/conan.py +0 -0
  26. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/direnv.py +0 -0
  27. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/docker.py +0 -0
  28. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/etc_hosts.py +0 -0
  29. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/files.py +0 -0
  30. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/flutter.py +0 -0
  31. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/google.py +0 -0
  32. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/intellij_idea.py +0 -0
  33. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/java.py +0 -0
  34. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/kubernetes.py +0 -0
  35. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/mobile.py +0 -0
  36. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/nodejs.py +0 -0
  37. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/npmrc.py +0 -0
  38. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/onepassword.py +0 -0
  39. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/pnpm.py +0 -0
  40. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/python.py +0 -0
  41. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/ssh.py +0 -0
  42. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/terraform.py +0 -0
  43. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_certs.py +0 -0
  44. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_intellij_idea.py +0 -0
  45. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_java.py +0 -0
  46. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_mobile.py +0 -0
  47. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_npmrc.py +0 -0
  48. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_onepassword.py +0 -0
  49. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_pnpm.py +0 -0
  50. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_ssh.py +0 -0
  51. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_yarn.py +0 -0
  52. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/xml.py +0 -0
  53. {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/yarn.py +0 -0
  54. {daktari-0.0.330 → daktari-0.0.332}/daktari/collection_utils.py +0 -0
  55. {daktari-0.0.330 → daktari-0.0.332}/daktari/command_utils.py +0 -0
  56. {daktari-0.0.330 → daktari-0.0.332}/daktari/config.py +0 -0
  57. {daktari-0.0.330 → daktari-0.0.332}/daktari/file_utils.py +0 -0
  58. {daktari-0.0.330 → daktari-0.0.332}/daktari/options.py +0 -0
  59. {daktari-0.0.330 → daktari-0.0.332}/daktari/os.py +0 -0
  60. {daktari-0.0.330 → daktari-0.0.332}/daktari/resource_utils.py +0 -0
  61. {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/__init__.py +0 -0
  62. {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/daktari-local-template.yaml +0 -0
  63. {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/mock_cert.pem +0 -0
  64. {daktari-0.0.330 → daktari-0.0.332}/daktari/result_printer.py +0 -0
  65. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_asdf.py +0 -0
  66. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check.py +0 -0
  67. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_factory.py +0 -0
  68. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_runner.py +0 -0
  69. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_sorter.py +0 -0
  70. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_utils.py +0 -0
  71. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_collection_utils.py +0 -0
  72. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_config.py +0 -0
  73. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_result_printer.py +0 -0
  74. {daktari-0.0.330 → daktari-0.0.332}/daktari/test_version_utils.py +0 -0
  75. {daktari-0.0.330 → daktari-0.0.332}/daktari/version_utils.py +0 -0
  76. {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/dependency_links.txt +0 -0
  77. {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/entry_points.txt +0 -0
  78. {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/requires.txt +0 -0
  79. {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/top_level.txt +0 -0
  80. {daktari-0.0.330 → daktari-0.0.332}/requirements.txt +0 -0
  81. {daktari-0.0.330 → daktari-0.0.332}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: daktari
3
- Version: 0.0.330
3
+ Version: 0.0.332
4
4
  Summary: Assist in setting up and maintaining developer environments
5
5
  Author-email: Matt Russell <matthew.russell@sonocent.com>
6
6
  License: Copyright 2021 Sonocent Ltd
@@ -45,7 +45,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
45
45
  ```python
46
46
  from daktari.checks.git import *
47
47
 
48
- version = "0.0.330"
48
+ version = "0.0.332"
49
49
  title = "My Project"
50
50
 
51
51
  checks = [
@@ -7,7 +7,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
7
7
  ```python
8
8
  from daktari.checks.git import *
9
9
 
10
- version = "0.0.330"
10
+ version = "0.0.332"
11
11
  title = "My Project"
12
12
 
13
13
  checks = [
@@ -0,0 +1 @@
1
+ __version__ = "0.0.332"
@@ -133,7 +133,8 @@ class PreCommitGitHooksInstalled(Check):
133
133
  }
134
134
 
135
135
  def check(self) -> CheckResult:
136
- git_hooks_installed = file_contains_text(".git/hooks/pre-commit", "pre-commit.com")
136
+ hook_path = get_stdout("git rev-parse --git-path hooks/pre-commit")
137
+ git_hooks_installed = hook_path is not None and file_contains_text(hook_path, "pre-commit.com")
137
138
  return self.verify(git_hooks_installed, "pre-commit Git hooks are <not/> installed")
138
139
 
139
140
 
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from os.path import expanduser
3
- from typing import Dict, Optional
3
+ from typing import Dict, Optional, Set
4
4
 
5
5
  from python_hosts import Hosts
6
6
 
@@ -189,9 +189,10 @@ class Md5SumInstalled(Check):
189
189
  class HostAliasesConfigured(Check):
190
190
  name = "hostAliases.configured"
191
191
 
192
- def __init__(self, required_aliases: Dict[str, str]):
192
+ def __init__(self, required_aliases: Dict[str, str], hosts_path: Optional[str] = None):
193
193
  self.required_aliases = required_aliases
194
- hosts_path = Hosts.determine_hosts_path()
194
+ self.hosts_path = hosts_path
195
+ hosts_path = hosts_path or Hosts.determine_hosts_path()
195
196
 
196
197
  aliases_by_addr: Dict[str, list[str]] = {}
197
198
 
@@ -209,15 +210,18 @@ class HostAliasesConfigured(Check):
209
210
  self.suggestions = {OS.GENERIC: suggestion_text}
210
211
 
211
212
  def check(self) -> CheckResult:
212
- hosts = Hosts()
213
+ hosts = Hosts(path=self.hosts_path)
213
214
  entries = [e for e in hosts.entries if e.entry_type in ("ipv4", "ipv6")]
214
- entries_dict = {}
215
+ # A hostname can legitimately map to several addresses (e.g. dual-stack
216
+ # localhost -> both 127.0.0.1 and ::1), so collect all addresses per name
217
+ # rather than letting the last entry in file order win.
218
+ entries_dict: Dict[str, Set[str]] = {}
215
219
  for entry in entries:
216
220
  for name in entry.names:
217
- entries_dict[name] = entry.address
221
+ entries_dict.setdefault(name, set()).add(entry.address)
218
222
  logging.debug(f"Hosts file entries: {entries_dict}")
219
223
  for name, address in self.required_aliases.items():
220
- if entries_dict.get(name) != address:
224
+ if address not in entries_dict.get(name, set()):
221
225
  return self.failed(f"{hosts.path} alias {name} -> {address} not present")
222
226
 
223
227
  return self.passed(f"{hosts.path} aliases present")
@@ -0,0 +1,53 @@
1
+ import os
2
+ import tempfile
3
+ import unittest
4
+
5
+ from daktari.check import CheckStatus
6
+ from daktari.checks.misc import HostAliasesConfigured
7
+
8
+ # Stock macOS /etc/hosts maps "localhost" to both 127.0.0.1 and ::1, with the
9
+ # ::1 line appearing last. The check must treat the IPv4 alias as satisfied
10
+ # regardless of the order the two lines appear in (see HostAliasesConfigured).
11
+ DUAL_STACK_IPV6_LAST = "127.0.0.1 localhost\n255.255.255.255 broadcasthost\n::1 localhost\n"
12
+ DUAL_STACK_IPV4_LAST = "::1 localhost\n255.255.255.255 broadcasthost\n127.0.0.1 localhost\n"
13
+
14
+
15
+ class TestHostAliasesConfigured(unittest.TestCase):
16
+ def _hosts_fixture(self, content):
17
+ f = tempfile.NamedTemporaryFile("w", suffix=".hosts", delete=False)
18
+ f.write(content)
19
+ f.close()
20
+ self.addCleanup(os.unlink, f.name)
21
+ return f.name
22
+
23
+ def test_checking_hosts_does_not_blow_up_on_success(self):
24
+ result = HostAliasesConfigured({}).check()
25
+ self.assertEqual(result.status, CheckStatus.PASS)
26
+
27
+ def test_checking_hosts_does_not_blow_up_on_failure(self):
28
+ result = HostAliasesConfigured({"host": "no.such.entry.surely"}).check()
29
+ self.assertEqual(result.status, CheckStatus.FAIL)
30
+
31
+ def test_dual_stack_alias_passes_with_ipv6_entry_last(self):
32
+ path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
33
+ result = HostAliasesConfigured({"localhost": "127.0.0.1"}, hosts_path=path).check()
34
+ self.assertEqual(result.status, CheckStatus.PASS)
35
+
36
+ def test_dual_stack_alias_passes_with_ipv4_entry_last(self):
37
+ path = self._hosts_fixture(DUAL_STACK_IPV4_LAST)
38
+ result = HostAliasesConfigured({"localhost": "127.0.0.1"}, hosts_path=path).check()
39
+ self.assertEqual(result.status, CheckStatus.PASS)
40
+
41
+ def test_dual_stack_ipv6_alias_also_satisfied(self):
42
+ path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
43
+ result = HostAliasesConfigured({"localhost": "::1"}, hosts_path=path).check()
44
+ self.assertEqual(result.status, CheckStatus.PASS)
45
+
46
+ def test_missing_alias_still_fails(self):
47
+ path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
48
+ result = HostAliasesConfigured({"localhost": "10.0.0.1"}, hosts_path=path).check()
49
+ self.assertEqual(result.status, CheckStatus.FAIL)
50
+
51
+
52
+ if __name__ == "__main__":
53
+ unittest.main()
@@ -0,0 +1,55 @@
1
+ import unittest
2
+ from unittest.mock import patch
3
+
4
+ from daktari.check import CheckStatus
5
+ from daktari.checks.git import PreCommitGitHooksInstalled
6
+
7
+ # The path git resolves the pre-commit hook to. In a worktree this is *not*
8
+ # ".git/hooks/pre-commit" (there ".git" is a file, not a directory), and when
9
+ # core.hooksPath is set it points outside the per-worktree gitdir entirely.
10
+ RESOLVED_HOOK_PATH = "/main/.git/hooks/pre-commit"
11
+ LITERAL_HOOK_PATH = ".git/hooks/pre-commit"
12
+
13
+
14
+ def fake_hook_contents(path: str, text: str) -> bool:
15
+ """Model a worktree: only the git-resolved hook path exists and is installed.
16
+
17
+ The literal ".git/hooks/pre-commit" path is absent (in a worktree ".git" is a
18
+ file), so reading it directly always misses.
19
+ """
20
+ return path == RESOLVED_HOOK_PATH and text == "pre-commit.com"
21
+
22
+
23
+ class TestPreCommitGitHooksInstalled(unittest.TestCase):
24
+ @patch("daktari.checks.git.file_contains_text", side_effect=fake_hook_contents)
25
+ @patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
26
+ def test_passes_in_worktree_when_hook_resolves_via_git(self, mock_get_stdout, mock_contains):
27
+ result = PreCommitGitHooksInstalled().check()
28
+ self.assertEqual(
29
+ result.status,
30
+ CheckStatus.PASS,
31
+ "Hooks are installed (resolved via git), so the check should pass even in a worktree",
32
+ )
33
+ mock_get_stdout.assert_called_once_with("git rev-parse --git-path hooks/pre-commit")
34
+
35
+ @patch("daktari.checks.git.file_contains_text", side_effect=fake_hook_contents)
36
+ @patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
37
+ def test_resolved_path_is_checked_not_literal(self, mock_get_stdout, mock_contains):
38
+ PreCommitGitHooksInstalled().check()
39
+ mock_contains.assert_called_once_with(RESOLVED_HOOK_PATH, "pre-commit.com")
40
+
41
+ @patch("daktari.checks.git.file_contains_text", return_value=False)
42
+ @patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
43
+ def test_fails_when_hook_not_installed(self, mock_get_stdout, mock_contains):
44
+ result = PreCommitGitHooksInstalled().check()
45
+ self.assertEqual(result.status, CheckStatus.FAIL)
46
+
47
+ @patch("daktari.checks.git.file_contains_text", return_value=False)
48
+ @patch("daktari.checks.git.get_stdout", return_value=None)
49
+ def test_fails_gracefully_when_git_cannot_resolve_path(self, mock_get_stdout, mock_contains):
50
+ result = PreCommitGitHooksInstalled().check()
51
+ self.assertEqual(result.status, CheckStatus.FAIL)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: daktari
3
- Version: 0.0.330
3
+ Version: 0.0.332
4
4
  Summary: Assist in setting up and maintaining developer environments
5
5
  Author-email: Matt Russell <matthew.russell@sonocent.com>
6
6
  License: Copyright 2021 Sonocent Ltd
@@ -45,7 +45,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
45
45
  ```python
46
46
  from daktari.checks.git import *
47
47
 
48
- version = "0.0.330"
48
+ version = "0.0.332"
49
49
  title = "My Project"
50
50
 
51
51
  checks = [
@@ -26,6 +26,7 @@ daktari/test_check_sorter.py
26
26
  daktari/test_check_utils.py
27
27
  daktari/test_collection_utils.py
28
28
  daktari/test_config.py
29
+ daktari/test_git.py
29
30
  daktari/test_result_printer.py
30
31
  daktari/test_version_utils.py
31
32
  daktari/version_utils.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "daktari"
7
- version = "0.0.330"
7
+ version = "0.0.332"
8
8
  description = "Assist in setting up and maintaining developer environments"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE.txt" }
@@ -1 +0,0 @@
1
- __version__ = "0.0.330"
@@ -1,18 +0,0 @@
1
- import unittest
2
-
3
- from daktari.check import CheckStatus
4
- from daktari.checks.misc import HostAliasesConfigured
5
-
6
-
7
- class TestHostAliasesConfigured(unittest.TestCase):
8
- def test_checking_hosts_does_not_blow_up_on_success(self):
9
- result = HostAliasesConfigured({}).check()
10
- self.assertEqual(result.status, CheckStatus.PASS)
11
-
12
- def test_checking_hosts_does_not_blow_up_on_failure(self):
13
- result = HostAliasesConfigured({"host": "no.such.entry.surely"}).check()
14
- self.assertEqual(result.status, CheckStatus.FAIL)
15
-
16
-
17
- if __name__ == "__main__":
18
- unittest.main()
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