API — ppbcc.code_complexity#
Module Overview#
Halstead complexity and LOC metrics for C++ and GPU-enriched C++.
The package analyses C++ sources (and the C-like kernel/shading languages used by GPU paradigms) and computes the Halstead complexity measures as well as line-based size metrics. Constructs of GPU programming models such as OpenMP, OpenACC, Kokkos, RAJA, Alpaka, CUDA, HIP, SYCL, OpenCL, Vulkan, Boost.Compute, WebGPU/WGSL, GLSL, Slang and Metal are recognised and counted as dialect operators, which allows separating the baseline C++ complexity from the share added by a paradigm.
Typical usage:
>>> from ppbcc.code_complexity import evaluate
>>> frame = evaluate([Path("src/")], language_dialect="kokkos",
... metrics=["halstead", "loc"], diff=True)
Analysis Pipeline#
Top-level analysis pipeline: from source paths to the metric DataFrame.
- ppbcc.code_complexity.evaluate.AGGREGATE_ROW_NAME: str = 'TOTAL'#
Name used in the
filecolumn of the aggregation row.
- ppbcc.code_complexity.evaluate.collect_source_files(sources)[source]#
Expands the given paths into a flat list of source files.
- Parameters:
sources (list[Path]) – Files and/or directories. Directories are searched recursively for files with an extension in
ppbcc.code_complexity.config.SOURCE_EXTENSIONS; explicitly listed files are taken as-is.- Returns:
Sorted list of unique source files.
- Raises:
FileNotFoundError – If one of the paths does not exist.
- Return type:
- ppbcc.code_complexity.evaluate.analyze_source(code, path, keywords, registry, dialects)[source]#
Analyses one source text.
- Parameters:
code (str) – Raw source text.
path (Path | None) – Path of the file (used for logging and auto-detection); may be
Nonefor in-memory analysis.keywords (CppKeywords) – Baseline C++ keyword sets.
registry (DialectRegistry) – The dialect registry.
dialects (list[DialectSpec] | None) – Active dialects, or
Noneto auto-detect them per file.
- Returns:
Tuple of the classified token counts, the line metrics and the names of the active dialects.
- Return type:
- ppbcc.code_complexity.evaluate.evaluate(sources, language_dialect='auto', metrics=None, *, diff=False, aggregate=False, output=None, csv_separator=',', keywords_path=None, dialects_path=None, exclude_macros=None, exclude_headers=None)[source]#
Runs the complexity analysis - the library’s top-level entry point.
- Parameters:
sources (list[Path]) – Source files and/or directories to analyse.
language_dialect (str) – Dialect selection:
"auto"(default) detects the dialects per file,"cpp"/"none"analyses plain C++, and any dialect name/alias (optionally comma-separated, e.g."kokkos,openmp") forces those dialects for all files.metrics (list[str] | None) – Metric names/groups to include as columns (e.g.
["halstead_effort", "loc"]);Noneselects all metrics.diff (bool) – If True, add
baseline_/delta_columns comparing the full metrics against the metrics without dialect tokens.aggregate (bool) – If True, append a
TOTALrow aggregating all files (operator/operand multisets are merged before recomputing the Halstead measures, so distinct counts are program-wide).output (Path | None) – Optional CSV destination; written when given.
csv_separator (str) – Field separator for the CSV output.
keywords_path (Path | None) – Optional override for the packaged
cpp_keywords.toml.dialects_path (Path | None) – Optional override for the packaged
dialects.toml.exclude_macros (list[str] | None) – Regular expressions for macro names whose invocations and conditionals are removed before the analysis, e.g.
["PPB_MARKER_\w+"](seeppbcc.code_complexity.exclude).exclude_headers (list[str] | None) – Glob patterns for headers which are neither analysed nor counted where they are included, e.g.
["common/Marker.h"].
- Returns:
DataFrame with one row per source file (plus the optional
TOTALrow) and the selected metric columns.- Raises:
FileNotFoundError – If a source path does not exist.
KeyError – If
language_dialectnames an unknown dialect.ValueError – If
metricscontains an unknown metric name, or a macro pattern is not a valid regular expression.
- Return type:
Exclusions#
Removal of code that should not count towards an implementation’s complexity.
A benchmark carries code that is not part of the algorithm it implements, most prominently profiler instrumentation: region markers around the kernels, and headers which define them. Such code would be counted as if every implementation had written it, so it is removed from the source text before the analysis, which then sees the program as if the instrumentation had never been added.
Two kinds of exclusion are supported:
Macros, given as regular expressions matched against the whole macro name.
An invocation of such a macro is removed together with its argument list and a directly following
;, e.g.PPB_MARKER_GPU_SCOPE("evaluate");.A conditional on such a macro (
#ifdef,#ifndef,#if defined(...),#if !defined(...),#if NAME) is resolved as if the macro was undefined: the branch the preprocessor would drop is removed with the directives, the branch it would keep stays. A conditional which combines the macro with other conditions is left untouched, with a warning.
Headers, given as glob patterns (e.g.
common/Marker.h) matched against the spelling of an#includeand against the tail of a file path. The#includedirective is removed, andis_excluded_file()tells callers which files to leave out altogether.
A line which held nothing but removed code (and possibly a comment) is removed entirely, so the line metrics shrink along with the Halstead counts.
- class ppbcc.code_complexity.exclude.Exclusions(macros=(), headers=())[source]#
Bases:
objectWhat to remove from the analysed code.
- Variables:
macros (tuple[re.Pattern[str], ...]) – Compiled patterns; a macro is excluded if one matches its whole name.
headers (tuple[str, ...]) – Glob patterns for excluded headers.
- Parameters:
- classmethod create(macros=None, headers=None)[source]#
Builds the exclusions from their textual patterns.
- Parameters:
- Returns:
The exclusions.
- Raises:
ValueError – If a macro pattern is not a valid regular expression.
- Return type:
- ppbcc.code_complexity.exclude.is_excluded_file(path, exclusions)[source]#
Whether
pathis an excluded header.A pattern matches the whole path or any trailing part of it, so
common/Marker.hmatches/repo/src/common/Marker.h.- Parameters:
path (Path) – The file in question.
exclusions (Exclusions) – The exclusions in effect.
- Returns:
True if the file is to be left out of the analysis.
- Return type:
- ppbcc.code_complexity.exclude.strip_excluded(code, exclusions, name='<string>')[source]#
Removes the excluded macros and headers from a source text.
- Parameters:
code (str) – Raw source text.
exclusions (Exclusions) – What to remove.
name (str) – Name of the source, used in warnings.
- Returns:
The source text without the excluded code; the text itself if there is nothing to exclude.
- Return type:
Tokenizer#
A lightweight lexer for C++ and C-like GPU/shading languages.
The lexer splits source text into Token objects (identifiers,
numbers, literals, punctuation, comments and preprocessor directives). It is
deliberately not a full C++ parser: it is precise enough for Halstead
counting and line classification, and it degrades gracefully on the C-like
shading languages (OpenCL C, GLSL, WGSL, Slang, Metal).
Special handling:
Comments and string/character literals are matched first, so their content never produces spurious tokens.
#include <header>is normalised so that the header name becomes a single (operand) token.#pragmalines are tracked: every token of a pragma line carries the pragma’s first word (e.g."omp") inToken.pragma, which lets the classifier attribute OpenMP/OpenACC directives to their dialect.Backslash line continuations inside pragma lines are honoured.
- class ppbcc.code_complexity.tokenizer.TokenKind(*values)[source]#
Bases:
EnumLexical category of a token.
- COMMENT = 1#
- STRING = 2#
- CHAR = 3#
- NUMBER = 4#
- IDENT = 5#
- PUNCT = 6#
- DIRECTIVE = 7#
- class ppbcc.code_complexity.tokenizer.Token(kind, text, line, end_line=0, pragma=None, start=-1, end=-1)[source]#
Bases:
objectA single lexical token.
- Variables:
kind (ppbcc.code_complexity.tokenizer.TokenKind) – Lexical category.
text (str) – Exact source text (directives are normalised to
#name).line (int) – 1-based line number of the token’s first character.
end_line (int) – 1-based line number of the token’s last character (differs from
lineonly for multi-line comments/raw strings).pragma (str | None) – First word of the surrounding
#pragmaline (e.g."omp") if the token is part of one, otherwiseNone.start (int) – Offset of the token’s first character in the source text (for a directive, the offset of its
#), or-1for a token built by hand. Not part of the token’s equality.end (int) – Offset one past the token’s last character, or
-1. Not part of the token’s equality.
- Parameters:
- ppbcc.code_complexity.tokenizer.CLOSING_BRACKETS: frozenset[str] = frozenset({')', ']', '}'})#
lexed, but skipped by the classifier because they pair with their (counted) opening bracket.
- Type:
Closing brackets
- ppbcc.code_complexity.tokenizer.KERNEL_LAUNCH_SPLIT: dict[str, tuple[str, ...]] = {'<<<': ('<<', '<'), '>>>': ('>>', '>')}#
Kernel-launch punctuation with its baseline C++ re-interpretation, used when no CUDA/HIP dialect is active.
- ppbcc.code_complexity.tokenizer.normalize_includes(code)[source]#
Rewrites
#include <header>to#include "header".The angle-bracket form would otherwise be lexed as comparison operators and identifiers; the string form yields a single operand token for the header name. The replacement preserves the text length and line numbers.
- ppbcc.code_complexity.tokenizer.tokenize(code)[source]#
Lexes source text into tokens.
- Parameters:
code (str) – Raw source text of a C++/C-like translation unit.
- Returns:
All tokens including comments (whitespace is dropped). Tokens inside
#pragmalines carry the pragma’s first word inToken.pragma.- Return type:
Token Classification#
Classification of lexer tokens into Halstead operators and operands.
The classifier consumes the token stream produced by
ppbcc.code_complexity.tokenizer and sorts every countable token into one of
four multisets:
operators – baseline C++ operators: keywords, punctuation, preprocessor directives.
operands – baseline C++ operands: identifiers, literals.
dialect operators – constructs contributed by an active GPU dialect: dialect keywords (
__global__), qualified names under a dialect namespace (Kokkos::parallel_forcounts as one operator), dialect pragmas and their clauses, kernel-launch punctuation, …dialect operands – values that only occur inside dialect constructs (e.g. the variables listed in an OpenMP
map(...)clause).
Counting conventions (documented here once, applied consistently):
Closing brackets
),],}pair with their opening bracket and are not counted separately.A qualified name that does not belong to a dialect is counted classically as its identifier segments (operands) joined by
::operators.true,false,nullptrandthiscount as operands.Namespace aliases (
namespace bc = boost::compute;) are resolved before dialect matching, sobc::vectoris recognised as Boost.Compute.
- class ppbcc.code_complexity.classification.TokenCounts(operators=<factory>, operands=<factory>, dialect_operators=<factory>, dialect_operands=<factory>)[source]#
Bases:
objectMultisets of classified tokens of one translation unit.
- Variables:
operators (collections.Counter[str]) – Baseline C++ operators keyed by token text.
operands (collections.Counter[str]) – Baseline C++ operands keyed by token text.
dialect_operators (collections.Counter[str]) – Dialect operators keyed by (qualified) token text.
dialect_operands (collections.Counter[str]) – Dialect operands keyed by token text.
- Parameters:
- merge(other)[source]#
Adds another unit’s counts in place (used for aggregation).
- Parameters:
other (TokenCounts) – Counts to merge into this instance.
- Return type:
None
- ppbcc.code_complexity.classification.extract_namespace_aliases(code)[source]#
Extracts C++ namespace alias definitions from source text.
- class ppbcc.code_complexity.classification.TokenClassifier(keywords, dialects, namespace_aliases=None)[source]#
Bases:
objectClassifies a token stream for a fixed set of active dialects.
- Parameters:
keywords (CppKeywords) – Baseline C++ keyword sets.
dialects (list[DialectSpec]) – Active dialect specifications; their constructs are counted as dialect operators. Pass an empty list for plain C++.
namespace_aliases (dict[str, tuple[str, ...]] | None) – Namespace aliases of the translation unit, as returned by
extract_namespace_aliases().
- classify(tokens)[source]#
Classifies all tokens into operator/operand multisets.
- Parameters:
tokens (list[Token]) – Token stream of one translation unit (comments included; they are skipped here).
- Returns:
The resulting
TokenCounts.- Return type:
Dialect Detection#
Automatic detection of the GPU dialects used by a source file.
When language_dialect="auto" is requested, every file is scanned for
strong dialect signals; a dialect is activated for the file if any of the
following matches:
the file extension is dialect-specific (
.cu,.hip,.cl, …),an
#includematches one of the dialect’s header patterns,a
#pragmaline starts with one of the dialect’s pragma prefixes,one of the dialect’s namespaces is used (
Kokkos::, also via a namespace alias), orat least
ppbcc.code_complexity.config.DETECTION_MIN_HITSoccurrences of the dialect’s weakerdetect_patternsare found.
A dialect detected only via detect_patterns is suppressed when a sibling
dialect sharing its keywords (e.g. CUDA and HIP both define threadIdx)
was detected with one of the stronger signals.
- ppbcc.code_complexity.detection.extract_includes(code)[source]#
Extracts all included header names from source text.
- ppbcc.code_complexity.detection.detect_dialects(code, path, registry)[source]#
Detects the dialects used by one source file.
- Parameters:
code (str) – Raw source text.
path (Path | None) – Path of the file (used for extension matching); may be
None.registry (DialectRegistry) – The dialect registry to match against.
- Returns:
The detected dialect specifications, in registry order (possibly empty for plain C++ code).
- Return type:
Halstead Metrics#
Computation of the Halstead complexity measures.
Given the operator/operand multisets produced by
ppbcc.code_complexity.classification, this module derives the classic
Halstead metrics (Maurice Halstead, Elements of Software Science, 1977):
Measure |
Formula |
|---|---|
Vocabulary |
|
Length |
|
Calculated length |
|
Volume |
|
Difficulty |
|
Effort |
|
Time |
|
Delivered bugs |
|
Program level |
|
Language level |
|
with n1/n2 the number of distinct operators/operands and N1/N2
their total number of occurrences.
- class ppbcc.code_complexity.halstead.HalsteadMetrics(distinct_operators, distinct_operands, total_operators, total_operands)[source]#
Bases:
objectThe Halstead base counts and derived measures of one program.
- Variables:
- Parameters:
- classmethod from_counts(operators, operands)[source]#
Builds the metrics from operator/operand multisets.
- Parameters:
- Returns:
The corresponding
HalsteadMetrics.- Return type:
Line Metrics#
Line-based size metrics (LOC/SLOC/comment/blank lines).
The classification is derived from the token stream so that multi-line
comments, comments behind code and string literals containing // are all
handled correctly:
LOC – total number of physical lines.
SLOC – lines containing at least one code token (a line with code and a trailing comment counts as source, not comment).
comment lines – lines whose only content is comment text.
blank lines – lines with neither code nor comments.
- class ppbcc.code_complexity.loc.LineMetrics(loc, sloc, comment_lines, blank_lines)[source]#
Bases:
objectLine counts of one source file.
- Variables:
- Parameters:
- combine(other)[source]#
Adds another file’s line counts (used for aggregation).
- Parameters:
other (LineMetrics) – Line counts to add.
- Returns:
A new
LineMetricswith the summed counts.- Return type:
- ppbcc.code_complexity.loc.count_lines(code, tokens)[source]#
Computes the line metrics of one source file.
- Parameters:
code (str) – Raw source text.
tokens (list[Token]) – Token stream of the same text, as produced by
ppbcc.code_complexity.tokenizer.tokenize().
- Returns:
The
LineMetricsof the file.- Return type:
Configuration#
Loading and representation of the analysis configuration.
The configuration consists of two TOML resources shipped with the package in
ppbcc/code_complexity/share:
cpp_keywords.toml– the baseline C++ keyword sets used to distinguish operators from operands.dialects.toml– the registry of GPU/parallel programming dialects (Kokkos, CUDA, OpenMP, …) whose constructs are counted as dialect operators.
Both files can be overridden with user-supplied paths, e.g. via the CLI.
- ppbcc.code_complexity.config.DETECTION_MIN_HITS: int = 3#
Number of
detect_patternshits in a source file required to activate a dialect during automatic detection (headers, file extensions, pragmas and namespace usage activate a dialect with a single hit instead).
- ppbcc.code_complexity.config.SOURCE_EXTENSIONS: frozenset[str] = frozenset({'.c', '.c++', '.cc', '.cl', '.comp', '.cpp', '.cu', '.cuh', '.cxx', '.frag', '.geom', '.glsl', '.h', '.h++', '.hh', '.hip', '.hlsl', '.hpp', '.hxx', '.inc', '.inl', '.ipp', '.metal', '.slang', '.tesc', '.tese', '.vert', '.wgsl'})#
File extensions collected when a directory is passed as a source.
- ppbcc.code_complexity.config.BASELINE_DIALECT_NAMES: frozenset[str] = frozenset({'baseline', 'c++', 'cpp', 'none'})#
Names of
language_dialectthat mean “plain C++, no dialect”.
- ppbcc.code_complexity.config.AUTO_DIALECT_NAME: str = 'auto'#
Name of the pseudo dialect that triggers automatic per-file detection.
- class ppbcc.code_complexity.config.CppKeywords(keywords, operand_keywords)[source]#
Bases:
objectBaseline C++ keyword sets.
- Variables:
- Parameters:
- class ppbcc.code_complexity.config.DialectSpec(name, aliases, namespace_prefixes=(), identifier_pattern=None, keywords=frozenset({}), pragma_prefixes=frozenset({}), pragma_clauses=frozenset({}), punctuation=frozenset({}), header_patterns=(), detect_patterns=(), extensions=frozenset({}))[source]#
Bases:
objectDescription of a single GPU/parallel-programming dialect.
All regular expressions are pre-compiled; identifier patterns are matched with
fullmatchagainst single identifiers, header and detection patterns withsearch.- Variables:
name (str) – Canonical dialect name (the table name in
dialects.toml).aliases (frozenset[str]) – Lower-case names accepted for
language_dialect.namespace_prefixes (tuple[tuple[str, ...], ...]) – Namespace prefixes (as tuples of segments) that turn a whole qualified name into a single dialect operator.
identifier_pattern (re.Pattern[str] | None) – Combined regex for dialect identifiers, or
Noneif the dialect defines no identifier patterns.keywords (frozenset[str]) – Exact identifiers belonging to the dialect.
pragma_prefixes (frozenset[str]) – First pragma tokens claiming a
#pragmaline.pragma_clauses (frozenset[str]) – Identifiers counted as operators inside a claimed pragma line (all other pragma identifiers count as operands).
punctuation (frozenset[str]) – Extra punctuation operators (e.g. CUDA
<<<).header_patterns (tuple[re.Pattern[str], ...]) – Regexes matched against included header names for automatic detection.
detect_patterns (tuple[re.Pattern[str], ...]) – Regexes searched in the raw source for automatic detection (requires
DETECTION_MIN_HITStotal hits).extensions (frozenset[str]) – File extensions that imply the dialect.
- Parameters:
name (str)
- class ppbcc.code_complexity.config.DialectRegistry(dialects, alias_map=<factory>)[source]#
Bases:
objectAll known dialects plus lookup helpers.
- Variables:
- Parameters:
- dialects: dict[str, DialectSpec]#
- resolve(name)[source]#
Resolves a dialect name or alias to its specification.
- Parameters:
name (str) – Dialect name or alias, case-insensitive (e.g.
"Kokkos").- Returns:
The matching
DialectSpec.- Raises:
KeyError – If the name is not a known dialect or alias.
- Return type:
- resolve_all(names)[source]#
Resolves a dialect selection string or list to specifications.
- Parameters:
names (str | list[str]) – Either a single (possibly comma-separated) string such as
"kokkos,openmp"or a list of dialect names. Baseline names ("cpp","none", …) resolve to an empty selection.- Returns:
List of resolved dialect specifications (without duplicates).
- Raises:
KeyError – If any name is neither a dialect alias nor a baseline name.
"auto"must be handled by the caller and also raises here.- Return type:
- ppbcc.code_complexity.config.load_cpp_keywords(path=None)[source]#
Loads the baseline C++ keyword sets.
- Parameters:
path (Path | None) – Optional path to a TOML file overriding the packaged
cpp_keywords.toml.- Returns:
The loaded
CppKeywords.- Return type:
- ppbcc.code_complexity.config.load_dialects(path=None)[source]#
Loads the dialect registry.
- Parameters:
path (Path | None) – Optional path to a TOML file overriding the packaged
dialects.toml.- Returns:
The loaded
DialectRegistrywith all regexes compiled.- Return type:
Reporting#
Result assembly: metric selection, DataFrame construction, CSV export.
- ppbcc.code_complexity.report.ID_COLUMNS: tuple[str, ...] = ('file', 'dialect')#
Identifier columns always present in the report.
- ppbcc.code_complexity.report.LOC_COLUMNS: tuple[str, ...] = ('loc', 'sloc', 'comment_lines', 'blank_lines')#
Line-metric columns (see
ppbcc.code_complexity.loc).
- ppbcc.code_complexity.report.HALSTEAD_COLUMNS: tuple[str, ...] = ('distinct_operators', 'distinct_operands', 'total_operators', 'total_operands', 'vocabulary', 'length', 'calculated_length', 'volume', 'difficulty', 'effort', 'time_seconds', 'delivered_bugs', 'program_level', 'language_level')#
Halstead columns (see
ppbcc.code_complexity.halstead), in report order.
- ppbcc.code_complexity.report.DIALECT_COLUMNS: tuple[str, ...] = ('dialect_distinct_operators', 'dialect_total_operators', 'dialect_distinct_operands', 'dialect_total_operands')#
Columns counting the tokens contributed by the GPU dialect(s).
- ppbcc.code_complexity.report.DIFF_COLUMNS: tuple[str, ...] = ('distinct_operators', 'distinct_operands', 'total_operators', 'total_operands', 'vocabulary', 'length', 'volume', 'difficulty', 'effort')#
Columns that additionally get
baseline_/delta_variants in diff mode (baseline = metrics of the code with all dialect tokens removed).
- ppbcc.code_complexity.report.METRIC_GROUPS: dict[str, tuple[str, ...]] = {'all': ('loc', 'sloc', 'comment_lines', 'blank_lines', 'distinct_operators', 'distinct_operands', 'total_operators', 'total_operands', 'vocabulary', 'length', 'calculated_length', 'volume', 'difficulty', 'effort', 'time_seconds', 'delivered_bugs', 'program_level', 'language_level', 'dialect_distinct_operators', 'dialect_total_operators', 'dialect_distinct_operands', 'dialect_total_operands'), 'dialect': ('dialect_distinct_operators', 'dialect_total_operators', 'dialect_distinct_operands', 'dialect_total_operands'), 'dialect_operators': ('dialect_distinct_operators', 'dialect_total_operators', 'dialect_distinct_operands', 'dialect_total_operands'), 'halstead': ('distinct_operators', 'distinct_operands', 'total_operators', 'total_operands', 'vocabulary', 'length', 'calculated_length', 'volume', 'difficulty', 'effort', 'time_seconds', 'delivered_bugs', 'program_level', 'language_level'), 'lines_of_code': ('loc', 'sloc', 'comment_lines', 'blank_lines'), 'loc': ('loc', 'sloc', 'comment_lines', 'blank_lines'), 'sloc': ('sloc',), 'source_lines_of_code': ('sloc',)}#
Metric-group names accepted by
evaluate(metrics=...)and the CLI.
- ppbcc.code_complexity.report.resolve_metric_columns(metrics)[source]#
Resolves metric names/groups to the report columns they select.
Accepted names are the group names in
METRIC_GROUPS, any single column name (e.g."effort","sloc") and Halstead columns with ahalstead_prefix (e.g."halstead_effort"). Matching is case-insensitive; spaces and dashes are treated as underscores.- Parameters:
metrics (list[str] | None) – Requested metric names, or
None/empty for all metrics.- Returns:
The selected column names in canonical report order (without the identifier columns).
- Raises:
ValueError – If a metric name is unknown.
- Return type:
- ppbcc.code_complexity.report.report_columns(metrics, diff)[source]#
Builds the full column list of the report.
- Parameters:
metrics (list[str] | None) – Requested metric names (see
resolve_metric_columns()).diff (bool) – If True, every selected column in
DIFF_COLUMNSis followed by itsbaseline_anddelta_variant.
- Returns:
The ordered column names, starting with
ID_COLUMNS.- Return type:
- ppbcc.code_complexity.report.to_dataframe(rows, metrics, diff)[source]#
Builds the report DataFrame from per-file result rows.
- Parameters:
- Returns:
DataFrame with one row per file and the selected metric columns.
- Return type:
- ppbcc.code_complexity.report.format_table(frame, table_format='rounded_outline')[source]#
Pretty-prints the report DataFrame as a text table.
Command Line Interface#
Command-line interface for code-complexity analysis.
Examples
Analyse a directory with automatic dialect detection and save a CSV:
python -m ppbcc.code_complexity path/to/src -o report.csv
Force the Kokkos dialect, restrict the metrics and show the difference to the plain-C++ baseline:
python -m ppbcc.code_complexity src/kokkos -d kokkos \
-m halstead_effort halstead_volume loc --diff -v
- ppbcc.code_complexity.cli.configure_logging(verbosity)[source]#
Configures the loguru sink according to the CLI verbosity.
- Parameters:
verbosity (int) – Number of
-vflags: 0 = INFO, 1 = DEBUG, >= 2 = TRACE.- Return type:
None
- ppbcc.code_complexity.cli.build_parser()[source]#
Builds the CLI argument parser.
- Returns:
The configured
argparse.ArgumentParser.- Return type: