Add the Crapper UML policy and diagram.

Generated from the Python package under src/crapper.
EOF && git status -sb && git log -3 --oneline
This commit is contained in:
Robert C. Martin
2026-09-30 08:38:17 -05:00
parent bd91c20ebf
commit 103df22cb5
4 changed files with 394 additions and 0 deletions
+1
View File
@@ -6,3 +6,4 @@ __pycache__/
target/ target/
dist/ dist/
build/ build/
uml-viewer-log.txt
+314
View File
@@ -0,0 +1,314 @@
;; Generated by clj -M:ir from the policy file. Do not edit.
{:hierarchical true,
:title "Crapper",
:prefix "crapper",
:edge-kinds {},
:omit-edges [],
:levels
[[:model :discover :crapper]
[:crap :coverage :metrics :report :languages]
[:analyze :runners]
[:cli]
[:__main__]],
:policy-file "examples/crapper.policy.edn",
:order
[:model
:discover
:crapper
:crap
:coverage
:metrics
:report
:languages
:analyze
:runners
:cli
:__main__],
:omit [],
:edges
[{:from :__main__, :to :cli, :kind :dependency}
{:from :languages.python, :to :languages.treesitter, :kind :dependency}
{:from :languages, :to :languages.typescript, :kind :dependency}
{:from :languages.rust, :to :languages.treesitter, :kind :dependency}
{:from :languages.java, :to :languages.treesitter, :kind :dependency}
{:from :crap, :to :model, :kind :implements}
{:from :languages.rust, :to :pathlib, :kind :dependency}
{:from :analyze, :to :pathlib, :kind :dependency}
{:from :languages.java, :to :re, :kind :dependency}
{:from :runners, :to :shlex, :kind :dependency}
{:from :coverage, :to :model, :kind :dependency}
{:from :languages.typescript, :to :languages.treesitter, :kind :dependency}
{:from :runners, :to :json, :kind :dependency}
{:from :languages.golang, :to :languages.language, :kind :inheritance}
{:from :cli, :to :subprocess, :kind :dependency}
{:from :languages.treesitter, :to :tree_sitter_language_pack, :kind :dependency}
{:from :languages.typescript, :to :model, :kind :dependency}
{:from :languages.golang, :to :pathlib, :kind :dependency}
{:from :coverage, :to :urllib, :kind :dependency}
{:from :analyze, :to :languages, :kind :dependency}
{:from :languages, :to :languages.clojure, :kind :dependency}
{:from :languages.python, :to :languages.language, :kind :inheritance}
{:from :report, :to :model, :kind :dependency}
{:from :languages.golang, :to :languages.treesitter, :kind :dependency}
{:from :languages, :to :languages.java, :kind :dependency}
{:from :coverage, :to :xml, :kind :dependency}
{:from :languages, :to :languages.python, :kind :dependency}
{:from :cli, :to :sys, :kind :dependency}
{:from :cli, :to :pathlib, :kind :dependency}
{:from :analyze, :to :model, :kind :dependency}
{:from :languages.clojure, :to :re, :kind :dependency}
{:from :languages.treesitter, :to :functools, :kind :dependency}
{:from :discover, :to :os, :kind :dependency}
{:from :analyze, :to :discover, :kind :dependency}
{:from :coverage, :to :pathlib, :kind :dependency}
{:from :languages.language, :to :model, :kind :dependency}
{:from :languages, :to :model, :kind :dependency}
{:from :analyze, :to :crap, :kind :dependency}
{:from :runners, :to :subprocess, :kind :dependency}
{:from :cli, :to :coverage, :kind :dependency}
{:from :languages, :to :languages.rust, :kind :dependency}
{:from :languages.typescript, :to :languages.language, :kind :inheritance}
{:from :cli, :to :report, :kind :dependency}
{:from :metrics, :to :pathlib, :kind :dependency}
{:from :runners, :to :shutil, :kind :dependency}
{:from :model, :to :dataclasses, :kind :dependency}
{:from :languages.rust, :to :languages.language, :kind :inheritance}
{:from :languages.java, :to :model, :kind :dependency}
{:from :languages.rust, :to :re, :kind :dependency}
{:from :cli, :to :dataclasses, :kind :dependency}
{:from :discover, :to :pathlib, :kind :dependency}
{:from :coverage, :to :dataclasses, :kind :dependency}
{:from :languages, :to :languages.language, :kind :dependency}
{:from :cli, :to :runners, :kind :dependency}
{:from :languages.clojure, :to :languages.language, :kind :inheritance}
{:from :languages.rust, :to :model, :kind :dependency}
{:from :runners, :to :sys, :kind :dependency}
{:from :languages.clojure, :to :model, :kind :dependency}
{:from :languages.golang, :to :model, :kind :dependency}
{:from :languages.java, :to :languages.language, :kind :inheritance}
{:from :languages.python, :to :model, :kind :dependency}
{:from :analyze, :to :coverage, :kind :dependency}
{:from :cli, :to :metrics, :kind :dependency}
{:from :runners, :to :discover, :kind :dependency}
{:from :languages, :to :languages.golang, :kind :dependency}
{:from :cli, :to :analyze, :kind :dependency}
{:from :coverage, :to :re, :kind :dependency}
{:from :metrics, :to :model, :kind :dependency}
{:from :cli, :to :discover, :kind :dependency}
{:from :runners, :to :pathlib, :kind :dependency}],
:classes
[{:ns "crapper",
:name "Crapper",
:file "src/crapper/__init__.py",
:level 0,
:lang :python,
:id :crapper}
{:ns "crapper.__main__",
:name "__main__",
:file "src/crapper/__main__.py",
:level 4,
:lang :python,
:id :__main__}
{:ns "crapper.analyze",
:name "Analyze",
:file "src/crapper/analyze.py",
:ops [{:name "analyze_files", :text "analyze_files"}],
:level 2,
:lang :python,
:id :analyze}
{:ns "crapper.cli",
:name "Cli",
:file "src/crapper/cli.py",
:ops
[{:name "Options", :text "Options"}
{:name "parse_args", :text "parse_args"}
{:name "select_files", :text "select_files"}
{:name "run", :text "run"}
{:name "main", :text "main"}],
:level 3,
:lang :python,
:id :cli}
{:ns "crapper.coverage",
:name "Coverage",
:file "src/crapper/coverage.py",
:ops
[{:name "normalize_path", :text "normalize_path"}
{:name "suffix_match", :text "suffix_match"}
{:name "coverage_percent", :text "coverage_percent"}
{:name "percent_for_range", :text "percent_for_range"}
{:name "parse_form_coverage", :text "parse_form_coverage"}
{:name "parse_lcov", :text "parse_lcov"}
{:name "parse_go_profile", :text "parse_go_profile"}
{:name "go_percent", :text "go_percent"}
{:name "JacocoMethod", :text "JacocoMethod"}
{:name "parse_jacoco_index", :text "parse_jacoco_index"}
{:name "CoverageBundle", :text "CoverageBundle"}
{:name "load_bundle", :text "load_bundle"}],
:level 1,
:lang :python,
:id :coverage}
{:ns "crapper.crap",
:name "Crap",
:file "src/crapper/crap.py",
:ops
[{:name "crap_score", :text "crap_score"}
{:name "round_metric", :text "round_metric"}
{:name "make_entry", :text "make_entry"}
{:name "sort_entries", :text "sort_entries"}],
:level 1,
:lang :python,
:id :crap}
{:ns "crapper.discover",
:name "Discover",
:file "src/crapper/discover.py",
:ops
[{:name "language_of", :text "language_of"}
{:name "is_test_file", :text "is_test_file"}
{:name "iter_source_files", :text "iter_source_files"}],
:level 0,
:lang :python,
:id :discover}
{:ns "crapper.languages",
:name "Languages",
:file "src/crapper/languages/__init__.py",
:ops [{:name "functions_in_file", :text "functions_in_file"}],
:level 1,
:lang :python,
:id :languages}
{:ns "crapper.languages.clojure",
:name "Clojure",
:file "src/crapper/languages/clojure.py",
:ops
[{:name "without_strings_and_comments", :text "without_strings_and_comments"}
{:name "cyclomatic_complexity", :text "cyclomatic_complexity"}
{:name "extract_functions", :text "extract_functions"}
{:name "declared_namespace", :text "declared_namespace"}
{:name "namespace_from_path", :text "namespace_from_path"}
{:name "functions_in_source", :text "functions_in_source"}
{:name "Clojure", :text "Clojure"}],
:level 1,
:lang :python,
:id :languages.clojure}
{:ns "crapper.languages.golang",
:name "Golang",
:file "src/crapper/languages/golang.py",
:ops
[{:name "package_namespace", :text "package_namespace"}
{:name "functions_in_source", :text "functions_in_source"}
{:name "Go", :text "Go"}],
:level 1,
:lang :python,
:id :languages.golang}
{:ns "crapper.languages.java",
:name "Java",
:file "src/crapper/languages/java.py",
:ops
[{:name "functions_in_source", :text "functions_in_source"}
{:name "Java", :text "Java"}],
:level 1,
:lang :python,
:id :languages.java}
{:ns "crapper.languages.language",
:name "Language",
:file "src/crapper/languages/language.py",
:ops [{:name "Language", :text "Language"} {:name "Unknown", :text "Unknown"}],
:level 1,
:lang :python,
:id :languages.language}
{:ns "crapper.languages.python",
:name "Python",
:file "src/crapper/languages/python.py",
:ops
[{:name "functions_in_source", :text "functions_in_source"}
{:name "Python", :text "Python"}],
:level 1,
:lang :python,
:id :languages.python}
{:ns "crapper.languages.rust",
:name "Rust",
:file "src/crapper/languages/rust.py",
:ops
[{:name "functions_in_source", :text "functions_in_source"}
{:name "Rust", :text "Rust"}],
:level 1,
:lang :python,
:id :languages.rust}
{:ns "crapper.languages.treesitter",
:name "Treesitter",
:file "src/crapper/languages/treesitter.py",
:ops
[{:name "parser_for", :text "parser_for"}
{:name "parse", :text "parse"}
{:name "node_text", :text "node_text"}
{:name "start_line", :text "start_line"}
{:name "end_line", :text "end_line"}
{:name "child_of_type", :text "child_of_type"}
{:name "descendants", :text "descendants"}
{:name "complexity", :text "complexity"}
{:name "binary_logic", :text "binary_logic"}],
:level 1,
:lang :python,
:id :languages.treesitter}
{:ns "crapper.languages.typescript",
:name "Typescript",
:file "src/crapper/languages/typescript.py",
:ops
[{:name "functions_in_source", :text "functions_in_source"}
{:name "TypeScript", :text "TypeScript"}],
:level 1,
:lang :python,
:id :languages.typescript}
{:ns "crapper.metrics",
:name "Metrics",
:file "src/crapper/metrics.py",
:ops
[{:name "metrics_path", :text "metrics_path"}
{:name "render_edn", :text "render_edn"}
{:name "write_metrics", :text "write_metrics"}],
:level 1,
:lang :python,
:id :metrics}
{:ns "crapper.model",
:name "Model",
:file "src/crapper/model.py",
:ops [{:name "Function", :text "Function"} {:name "Entry", :text "Entry"}],
:level 0,
:lang :python,
:id :model}
{:ns "crapper.report",
:name "Report",
:file "src/crapper/report.py",
:ops [{:name "format_report", :text "format_report"}],
:level 1,
:lang :python,
:id :report}
{:ns "crapper.runners",
:name "Runners",
:file "src/crapper/runners.py",
:ops
[{:name "run_shell", :text "run_shell"}
{:name "typescript_packages", :text "typescript_packages"}
{:name "typescript_command", :text "typescript_command"}
{:name "rust_modules", :text "rust_modules"}
{:name "python_roots", :text "python_roots"}
{:name "uses_pytest", :text "uses_pytest"}
{:name "python_sources", :text "python_sources"}
{:name "python_coverage_commands", :text "python_coverage_commands"}
{:name "rust_coverage_command", :text "rust_coverage_command"}
{:name "run_coverage", :text "run_coverage"}],
:level 2,
:lang :python,
:id :runners}
{:id :dataclasses, :name "dataclasses", :foreign true}
{:id :functools, :name "functools", :foreign true}
{:id :json, :name "json", :foreign true}
{:id :os, :name "os", :foreign true}
{:id :pathlib, :name "pathlib", :foreign true}
{:id :re, :name "re", :foreign true}
{:id :shlex, :name "shlex", :foreign true}
{:id :shutil, :name "shutil", :foreign true}
{:id :subprocess, :name "subprocess", :foreign true}
{:id :sys, :name "sys", :foreign true}
{:id :tree_sitter_language_pack, :name "tree_sitter_language_pack", :foreign true}
{:id :urllib, :name "urllib", :foreign true}
{:id :xml, :name "xml", :foreign true}]}
+18
View File
@@ -0,0 +1,18 @@
{:title "Crapper"
:prefix "crapper"
:lang :python
:src "src"
:out "examples/crapper.edn"
:hierarchical true
:foreign [dataclasses functools json os pathlib re shlex shutil subprocess sys
tree_sitter_language_pack urllib xml]
:order [model discover crapper
crap coverage metrics report languages
analyze runners
cli
__main__]
:levels [[model discover crapper]
[crap coverage metrics report languages]
[analyze runners]
[cli]
[__main__]]}
Executable
+61
View File
@@ -0,0 +1,61 @@
#!/bin/zsh
# Loader for this project. Points at the local uml-viewer checkout so the
# Python scanner is on the classpath.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
cd "$ROOT"
DEPS='{:deps {uml-viewer/uml-viewer {:local/root "/Users/unclebob/projects/uml-viewer"} quil/quil {:mvn/version "4.3.1563"}}}'
edn_path() {
local name base f
name="$(basename "$ROOT")"
if [[ -f "examples/${name}.edn" ]]; then
echo "examples/${name}.edn"
return
fi
if [[ -d examples ]]; then
for f in examples/*.edn(N); do
[[ -f "$f" ]] || continue
base="${f:t}"
[[ "$base" == *.policy.edn ]] && continue
echo "$f"
return
done
fi
}
LOG="uml-viewer-log.txt"
launch_viewer() {
{
printf '----- %s starting uml-viewer' "$(date '+%Y-%m-%d %H:%M:%S')"
[[ $# -gt 0 ]] && printf ' %s' "$@"
printf '\n'
} >> "$LOG"
# `clj` is rlwrap on Homebrew; a background rlwrap stops (SIGTTOU) and
# never starts the JVM. `clojure` is the same CLI without the tty wrapper.
nohup clojure -Sdeps "$DEPS" -M -m uml-viewer.main.uml-viewer "$@" >> "$LOG" 2>&1 </dev/null &
disown
echo "UML viewer started (pid $!). Log: $LOG"
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
echo "usage: ./uml [--restart]" >&2
echo " (no args) fresh window; companion writes the diagram" >&2
echo " --restart new JVM, same companion; restores last view" >&2
echo " The viewer detaches; exceptions go to $LOG." >&2
exit 0
fi
if [[ "${1:-}" == "--restart" ]]; then
edn="$(edn_path)"
if [[ -n "$edn" ]]; then
launch_viewer --restart "$edn"
else
launch_viewer --restart
fi
exit 0
fi
launch_viewer "$@"