gitmole 0.9.0__tar.gz → 0.9.1__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 (64) hide show
  1. {gitmole-0.9.0 → gitmole-0.9.1}/PKG-INFO +2 -2
  2. {gitmole-0.9.0 → gitmole-0.9.1}/README.md +1 -1
  3. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/__init__.py +1 -1
  4. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/render.py +6 -2
  5. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/watch.py +1 -1
  6. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/PKG-INFO +2 -2
  7. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_render.py +13 -3
  8. {gitmole-0.9.0 → gitmole-0.9.1}/LICENSE +0 -0
  9. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/__main__.py +0 -0
  10. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/backtest.py +0 -0
  11. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/banner.py +0 -0
  12. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/blame.py +0 -0
  13. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/clean.py +0 -0
  14. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/cli.py +0 -0
  15. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/coupling.py +0 -0
  16. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/deps.py +0 -0
  17. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/duplicates.py +0 -0
  18. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/evaluate.py +0 -0
  19. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/filetypes.py +0 -0
  20. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/findings.py +0 -0
  21. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/functions.py +0 -0
  22. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/hotspots.py +0 -0
  23. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/identity.py +0 -0
  24. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/knowledge.py +0 -0
  25. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/leaks.py +0 -0
  26. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/load.py +0 -0
  27. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/loss.py +0 -0
  28. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/maat.py +0 -0
  29. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/run.py +0 -0
  30. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/textfmt.py +0 -0
  31. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole/trend.py +0 -0
  32. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/SOURCES.txt +0 -0
  33. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/dependency_links.txt +0 -0
  34. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/entry_points.txt +0 -0
  35. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/requires.txt +0 -0
  36. {gitmole-0.9.0 → gitmole-0.9.1}/gitmole.egg-info/top_level.txt +0 -0
  37. {gitmole-0.9.0 → gitmole-0.9.1}/pyproject.toml +0 -0
  38. {gitmole-0.9.0 → gitmole-0.9.1}/setup.cfg +0 -0
  39. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_backtest.py +0 -0
  40. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_banner.py +0 -0
  41. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_blame.py +0 -0
  42. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_clean.py +0 -0
  43. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_cli.py +0 -0
  44. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_coupling.py +0 -0
  45. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_deps.py +0 -0
  46. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_duplicates.py +0 -0
  47. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_evaluate.py +0 -0
  48. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_filetypes.py +0 -0
  49. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_findings.py +0 -0
  50. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_functions.py +0 -0
  51. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_golden.py +0 -0
  52. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_hotspots.py +0 -0
  53. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_identity.py +0 -0
  54. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_knowledge.py +0 -0
  55. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_leaks.py +0 -0
  56. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_load.py +0 -0
  57. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_loss.py +0 -0
  58. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_maat.py +0 -0
  59. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_packaging.py +0 -0
  60. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_render_examples.py +0 -0
  61. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_run.py +0 -0
  62. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_textfmt.py +0 -0
  63. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_trend.py +0 -0
  64. {gitmole-0.9.0 → gitmole-0.9.1}/tests/test_watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitmole
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Offline git repository analysis with a terminal report: hotspots, coupling, ownership, code age, secrets, repo health.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/antvinni/gitmole
@@ -96,7 +96,7 @@ since 2013, at a pinned commit:
96
96
  ork.js commitLayoutEffectOnFiber() complexity 72
97
97
  packages/react-reconciler/src/ReactFiberBeginWo changed 361 times · fixed once in six months ·
98
98
  rk.js beginWork() complexity 52
99
- ranked by revisions × lines of code; the reasons say what else counts against each file
99
+ ranked by revisions × lines of code alone; the reasons say what to look at there
100
100
  6 months ago this list would have named 11 of the 46 files fixed since (a random 15 of the 1802
101
101
  files that had changed more than once would name 0.3; the 15 most changed would name 7)
102
102
  ```
@@ -76,7 +76,7 @@ since 2013, at a pinned commit:
76
76
  ork.js commitLayoutEffectOnFiber() complexity 72
77
77
  packages/react-reconciler/src/ReactFiberBeginWo changed 361 times · fixed once in six months ·
78
78
  rk.js beginWork() complexity 52
79
- ranked by revisions × lines of code; the reasons say what else counts against each file
79
+ ranked by revisions × lines of code alone; the reasons say what to look at there
80
80
  6 months ago this list would have named 11 of the 46 files fixed since (a random 15 of the 1802
81
81
  files that had changed more than once would name 0.3; the 15 most changed would name 7)
82
82
  ```
@@ -1,3 +1,3 @@
1
1
  """gitmole: offline git repository analysis with a terminal report."""
2
2
 
3
- __version__ = "0.9.0"
3
+ __version__ = "0.9.1"
@@ -297,10 +297,14 @@ def watch_section(report: dict, full: bool = True, width=None) -> dict:
297
297
  rows = [(r["file"], " · ".join(r["reasons"])) for r in ranked[:limit]]
298
298
  columns = [("file", PATH), ("why", {"overflow": "fold", "ratio": 3})]
299
299
  since = report["meta"].get("since")
300
- notes = ["ranked by revisions × lines of code; the reasons say what else counts against each file" + (f"; commits since {since}" if since else "")]
300
+ # "alone": the reasons never move a file; a reader who sees fixes and ownership beside each row
301
+ # would otherwise take them for the ranking
302
+ notes = ["ranked by revisions × lines of code alone; the reasons say what to look at there" + (f"; commits since {since}" if since else "")]
301
303
  bt = watch.backtest(report)
302
304
  status = report["meta"].get("backtest") or {}
303
- if bt:
305
+ if bt and not bt["fixed"]:
306
+ notes.append("nothing has been fixed since the cut-off six months ago, so there is nothing to score the list against")
307
+ elif bt:
304
308
  notes.append(f"6 months ago this list would have named {bt['hits']} of the {bt['fixed']} files fixed since "
305
309
  f"(a random {bt['listed']} of the {bt['pool']} files that had changed more than once would name {bt['expected']}; "
306
310
  f"the {bt['listed']} most changed would name {bt['baselines']['churn']})"
@@ -1,4 +1,4 @@
1
- """The watch list: the source files most likely to be fixed next, and what else counts against each.
1
+ """The watch list: the source files most likely to be fixed next, and what to look at in each.
2
2
 
3
3
  Each source file that is still in the tree and changed more than once is ranked by revisions × lines
4
4
  of code, the product the Hotspots table uses: measured at six cut-offs on three repositories
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitmole
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Offline git repository analysis with a terminal report: hotspots, coupling, ownership, code age, secrets, repo health.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/antvinni/gitmole
@@ -96,7 +96,7 @@ since 2013, at a pinned commit:
96
96
  ork.js commitLayoutEffectOnFiber() complexity 72
97
97
  packages/react-reconciler/src/ReactFiberBeginWo changed 361 times · fixed once in six months ·
98
98
  rk.js beginWork() complexity 52
99
- ranked by revisions × lines of code; the reasons say what else counts against each file
99
+ ranked by revisions × lines of code alone; the reasons say what to look at there
100
100
  6 months ago this list would have named 11 of the 46 files fixed since (a random 15 of the 1802
101
101
  files that had changed more than once would name 0.3; the 15 most changed would name 7)
102
102
  ```
@@ -307,6 +307,16 @@ class Report(unittest.TestCase):
307
307
  self.assertEqual(render.to_json(r, [])["watch_backtest"]["pool"], 2)
308
308
  self.assertEqual(render.to_json(r, [])["watch_backtest"]["baselines"]["churn"], 1)
309
309
 
310
+ def test_nothing_fixed_since_the_cut_off_is_one_sentence_not_three_zeros(self):
311
+ r = sample_report()
312
+ past = sample_report()
313
+ past["meta"] = {"now": "2026-03-10"}
314
+ r["backtest"] = past
315
+ r["fixes"] = [{"entity": "static/index.html", "n-fixes": 1, "last-fix": "2026-01-01", "recent-fixes": 0}] # before the cut-off
316
+ caption = next(x for x in render.sections(r, full=False) if x["id"] == "watch")["caption"]
317
+ self.assertIn("nothing has been fixed since the cut-off six months ago, so there is nothing to score the list against", caption)
318
+ self.assertNotIn("0 of the 0", caption)
319
+ self.assertEqual(render.to_json(r, [])["watch_backtest"]["fixed"], 0, "the JSON keeps the numbers")
310
320
 
311
321
  def test_backtest_caption_says_whole_history_under_a_window(self):
312
322
  r = sample_report()
@@ -317,7 +327,7 @@ class Report(unittest.TestCase):
317
327
  {"entity": "static/other.html", "n-fixes": 1, "last-fix": "2026-08-01", "recent-fixes": 1}]
318
328
  r["meta"]["since"] = "2026-01-01"
319
329
  caption = next(x for x in render.sections(r, full=False) if x["id"] == "watch")["caption"]
320
- self.assertIn("ranked by revisions × lines of code; the reasons say what else counts against each file; commits since 2026-01-01", caption)
330
+ self.assertIn("ranked by revisions × lines of code alone; the reasons say what to look at there; commits since 2026-01-01", caption)
321
331
  self.assertTrue(caption.endswith("the 2 most changed would name 1); whole history"), caption)
322
332
 
323
333
  def test_markdown_hotspots_hide_test_files_and_say_so(self):
@@ -707,7 +717,7 @@ class WatchList(unittest.TestCase):
707
717
  self.assertIn("◎ Watch list", text)
708
718
  self.assertRegex(text, r"static/index.html\s+changed 51 times · only Ann has touched it")
709
719
  self.assertRegex(text, r"static/apps-metadata.json\s+changed 128 times · fixed 4 times in six months")
710
- self.assertIn("ranked by revisions × lines of code; the reasons say what else counts against each file", text)
720
+ self.assertIn("ranked by revisions × lines of code alone; the reasons say what to look at there", text)
711
721
 
712
722
  def test_capped_at_five_by_default_and_fifteen_in_full(self):
713
723
  r = sample_report()
@@ -748,7 +758,7 @@ class WatchList(unittest.TestCase):
748
758
  r = sample_report()
749
759
  r["meta"]["since"] = "2025-01-01"
750
760
  sec = next(x for x in render.sections(r, full=False) if x["id"] == "watch")
751
- self.assertEqual(sec["caption"], "ranked by revisions × lines of code; the reasons say what else counts against each file; commits since 2025-01-01")
761
+ self.assertEqual(sec["caption"], "ranked by revisions × lines of code alone; the reasons say what to look at there; commits since 2025-01-01")
752
762
 
753
763
 
754
764
  class FullOnlySections(unittest.TestCase):
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
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
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
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
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