From e19120420dc68adad8509aa41c193ec616e2cdf8 Mon Sep 17 00:00:00 2001 From: Matthew Horridge Date: Thu, 9 Jul 2026 11:11:01 -0700 Subject: [PATCH] Improve primitive docstring summaries for --list-operations Rewrite each primitive's opening docstring paragraph in a consistent imperative voice, naming the operation's serialized settings inline (e.g. "Add a constant `offset` (number) to numeric values") so the --list-operations output tells rule authors and AI agents how to configure an operation, not just what it does. Terse "Operator that ..." one-liners are replaced throughout. Co-Authored-By: Claude Fable 5 --- README.md | 7 ++++--- src/harmonization_framework/primitives/bin_primitive.py | 5 ++++- src/harmonization_framework/primitives/cast.py | 4 ++-- src/harmonization_framework/primitives/dates.py | 3 ++- src/harmonization_framework/primitives/donothing.py | 6 +++++- src/harmonization_framework/primitives/enum2enum.py | 7 ++++--- src/harmonization_framework/primitives/extract_regex.py | 3 ++- src/harmonization_framework/primitives/format_number.py | 3 ++- src/harmonization_framework/primitives/map_each.py | 2 +- src/harmonization_framework/primitives/missing_code.py | 4 +++- src/harmonization_framework/primitives/normalize.py | 3 ++- .../primitives/normalize_boolean.py | 4 +++- src/harmonization_framework/primitives/offset.py | 2 +- src/harmonization_framework/primitives/parse_array.py | 8 +++++--- src/harmonization_framework/primitives/reduce.py | 8 +++++--- src/harmonization_framework/primitives/round_decimal.py | 2 +- src/harmonization_framework/primitives/scale.py | 2 +- src/harmonization_framework/primitives/substitute.py | 3 ++- src/harmonization_framework/primitives/threshold.py | 3 ++- src/harmonization_framework/primitives/truncate.py | 2 +- src/harmonization_framework/primitives/units.py | 6 ++++-- .../primitives/validate_pattern.py | 3 ++- tests/test_list_operations.py | 2 +- 23 files changed, 59 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 055a160..945ee7d 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,14 @@ This prints every operation with a short description, for example: ``` convert_units - Convert numeric values between units using `pint`. + Convert numeric values from `source_unit` to `target_unit` — for example + `inch` to `cm`, or `kilogram` to `pound`. do_nothing - Operator that does nothing. + Pass the value through unchanged. Takes no settings. ``` -The descriptions are taken from the primitive implementations themselves, so the listing always matches the operations the installed version actually supports. +The descriptions are taken from the primitive implementations themselves, so the listing always matches the operations the installed version actually supports. Each description names the operation's settings (in backticks), matching the fields used in rules files. For a machine-readable listing, add `--format json`: diff --git a/src/harmonization_framework/primitives/bin_primitive.py b/src/harmonization_framework/primitives/bin_primitive.py index 98b7785..eea5dc3 100644 --- a/src/harmonization_framework/primitives/bin_primitive.py +++ b/src/harmonization_framework/primitives/bin_primitive.py @@ -16,7 +16,10 @@ def __init__(self, label: Any, lower: int, upper: int, left=None, right=None): class Bin(PrimitiveOperation): """ - Assign values into histogram bins. + Bucket numeric values into non-overlapping labelled ranges and return the + matching bin's label. `bins` is a list of `{label, start, end}` entries + with inclusive bounds. + Performs a range query using an interval tree. Bins must not overlap. """ def __init__(self, bins: List[Tuple[Any, Tuple[int, int]]]): diff --git a/src/harmonization_framework/primitives/cast.py b/src/harmonization_framework/primitives/cast.py index 437bac4..1d54349 100644 --- a/src/harmonization_framework/primitives/cast.py +++ b/src/harmonization_framework/primitives/cast.py @@ -11,9 +11,9 @@ class CastType(Enum): class Cast(PrimitiveOperation): """ - Cast values between supported primitive types. + Convert values from `source` type to `target` type: `text`, `integer`, + `boolean`, `decimal`, or `float`. - Supported targets: "text", "integer", "boolean", "decimal", "float". Boolean casting accepts common string/number representations. """ def __init__(self, source: str, target: str): diff --git a/src/harmonization_framework/primitives/dates.py b/src/harmonization_framework/primitives/dates.py index 5f0d964..1b88592 100644 --- a/src/harmonization_framework/primitives/dates.py +++ b/src/harmonization_framework/primitives/dates.py @@ -3,7 +3,8 @@ class ConvertDate(PrimitiveOperation): """ - Convert between date/time string formats using strptime/strftime. + Convert date/time strings from `source_format` to `target_format`, both + given as strftime patterns. Examples: - source_format="%Y-%m-%d", target_format="%m/%d/%Y" diff --git a/src/harmonization_framework/primitives/donothing.py b/src/harmonization_framework/primitives/donothing.py index e2d763d..781c7cf 100644 --- a/src/harmonization_framework/primitives/donothing.py +++ b/src/harmonization_framework/primitives/donothing.py @@ -3,7 +3,11 @@ class DoNothing(PrimitiveOperation): """ - Operator that does nothing. + Pass the value through unchanged. Takes no settings. + + Useful as an explicit placeholder where an operation chain is required + but no transformation is wanted — for example a `case`/`coalesce` branch + that uses a column as-is. """ def __str__(self): return "Do Nothing" diff --git a/src/harmonization_framework/primitives/enum2enum.py b/src/harmonization_framework/primitives/enum2enum.py index ad8526e..52fa41e 100644 --- a/src/harmonization_framework/primitives/enum2enum.py +++ b/src/harmonization_framework/primitives/enum2enum.py @@ -7,10 +7,11 @@ class EnumToEnum(PrimitiveOperation): """ - Operator that maps an input based on its prescribed mapping. + Map discrete values to replacement values via `mapping`, serialized as a + list of `{from, to}` entries. - If strict is True, missing mappings raise a KeyError. - If strict is False, missing mappings return the configured default (or None). + If `strict` is true, unmapped values raise a KeyError. + If `strict` is false, unmapped values return `default` (or None). """ def __init__(self, mapping: Dict[Any, Any], default: Any = None, strict: bool = False): """ diff --git a/src/harmonization_framework/primitives/extract_regex.py b/src/harmonization_framework/primitives/extract_regex.py index 3c0b674..c546aaf 100644 --- a/src/harmonization_framework/primitives/extract_regex.py +++ b/src/harmonization_framework/primitives/extract_regex.py @@ -30,7 +30,8 @@ def _resolve_flags(flag_names: Optional[Iterable[str]]) -> int: class ExtractRegex(PrimitiveOperation): """ - Extract a value from a string using a regex capture group. + Extract capture group `group` from the match of regex `expression` + against string values. Common harmonization use cases include pulling identifiers out of free text (e.g., MRN: A12-99) or numeric suffixes out of structured codes. diff --git a/src/harmonization_framework/primitives/format_number.py b/src/harmonization_framework/primitives/format_number.py index 808104d..f9a3d51 100644 --- a/src/harmonization_framework/primitives/format_number.py +++ b/src/harmonization_framework/primitives/format_number.py @@ -3,9 +3,10 @@ class FormatNumber(PrimitiveOperation): """ - Format numeric values to a fixed number of decimal places. + Format numeric values as text with exactly `precision` decimal places. Output is a string, intended for stable presentation (e.g., CSV output). + Use `round` instead to keep the value numeric. """ def __init__(self, precision: int): if not isinstance(precision, int): diff --git a/src/harmonization_framework/primitives/map_each.py b/src/harmonization_framework/primitives/map_each.py index 5fd9b92..7bc73de 100644 --- a/src/harmonization_framework/primitives/map_each.py +++ b/src/harmonization_framework/primitives/map_each.py @@ -5,7 +5,7 @@ class MapEach(PrimitiveOperation): """ - Apply a nested chain of operations to each element of a list. + Apply a nested chain of `operations` to each element of a list. Useful for multi-source rules where each source value needs the same per-element transform (e.g. cast each one-hot flag to int) before a diff --git a/src/harmonization_framework/primitives/missing_code.py b/src/harmonization_framework/primitives/missing_code.py index 46fc90f..6cfce8c 100644 --- a/src/harmonization_framework/primitives/missing_code.py +++ b/src/harmonization_framework/primitives/missing_code.py @@ -5,7 +5,9 @@ class MissingCode(PrimitiveOperation): """ - Operator that turns a column's missing-value codes into real nulls. + Map a column's declared missing-value `codes` (e.g. `-999`, `"UNK"`) to + real nulls; every other value passes through unchanged. Serialize codes as + a list of `{code, label}` entries, and place this first in a rule's chain. Real datasets frequently encode "missing" as an in-band sentinel value — a numeric code like -999 or a token like "UNK" — rather than as an empty cell. diff --git a/src/harmonization_framework/primitives/normalize.py b/src/harmonization_framework/primitives/normalize.py index 99a630b..e66d59d 100644 --- a/src/harmonization_framework/primitives/normalize.py +++ b/src/harmonization_framework/primitives/normalize.py @@ -14,7 +14,8 @@ class Normalization(Enum): class NormalizeText(PrimitiveOperation): """ - Perform a text normalization operation. + Apply a single text `normalization`: `strip`, `lower`, `upper`, + `remove_accents`, `remove_punctuation`, or `remove_special_characters`. """ def __init__(self, normalization: Normalization): self.normalization = normalization diff --git a/src/harmonization_framework/primitives/normalize_boolean.py b/src/harmonization_framework/primitives/normalize_boolean.py index c71ecd7..43d2fe3 100644 --- a/src/harmonization_framework/primitives/normalize_boolean.py +++ b/src/harmonization_framework/primitives/normalize_boolean.py @@ -4,7 +4,9 @@ class NormalizeBoolean(PrimitiveOperation): """ - Normalize common truthy/falsy representations to booleans. + Normalize truthy/falsy representations to booleans, using the `truthy` + and `falsy` value lists (sensible defaults provided). With `strict` false, + unrecognized values become `default` instead of raising. This primitive is intended for datasets that encode booleans as strings or numeric flags (e.g., "Yes", "y", "1", "no", "0"). diff --git a/src/harmonization_framework/primitives/offset.py b/src/harmonization_framework/primitives/offset.py index 9d87809..fbfdd0f 100644 --- a/src/harmonization_framework/primitives/offset.py +++ b/src/harmonization_framework/primitives/offset.py @@ -3,7 +3,7 @@ class Offset(PrimitiveOperation): """ - Operator that applies an offset to a numerical value. + Add a constant `offset` (number) to numeric values. """ def __init__(self, offset: Union[int, float]): if not isinstance(offset, (int, float)): diff --git a/src/harmonization_framework/primitives/parse_array.py b/src/harmonization_framework/primitives/parse_array.py index beae9ac..36eb441 100644 --- a/src/harmonization_framework/primitives/parse_array.py +++ b/src/harmonization_framework/primitives/parse_array.py @@ -7,11 +7,13 @@ class ParseArray(PrimitiveOperation): """ - Parse array-like values into Python lists. + Parse array-like text (e.g. "[8,8,6]" or "8|8|6") into a list, optionally + casting elements to `item_type`. Chain before a list-consuming operation + like `reduce`. - Supported formats: + Supported `format` values: - json: parse JSON arrays from strings (default) - - delimiter: split strings by a configured delimiter + - delimiter: split strings by the configured `delimiter` """ SUPPORTED_FORMATS = {"json", "delimiter"} diff --git a/src/harmonization_framework/primitives/reduce.py b/src/harmonization_framework/primitives/reduce.py index 39c16fa..13d8ab9 100644 --- a/src/harmonization_framework/primitives/reduce.py +++ b/src/harmonization_framework/primitives/reduce.py @@ -18,10 +18,12 @@ class Reduction(Enum): class Reduce(PrimitiveOperation): """ - Reduction operation that transforms N inputs to 1 output. + Reduce a list of values to a single value using `reduction`: `any`, + `none`, `all`, `one-hot`, or `sum`. - This primitive expects a single list/tuple of values as input and returns - one reduced value (e.g., sum, any, all). It does not accept scalar input. + This primitive expects a single list/tuple of values as input (e.g. from + `parse_array` or a multi-source rule) and returns one reduced value. It + does not accept scalar input. """ def __init__(self, reduction: Reduction): self.reduction = reduction diff --git a/src/harmonization_framework/primitives/round_decimal.py b/src/harmonization_framework/primitives/round_decimal.py index 3531bd4..e953d1f 100644 --- a/src/harmonization_framework/primitives/round_decimal.py +++ b/src/harmonization_framework/primitives/round_decimal.py @@ -3,7 +3,7 @@ class Round(PrimitiveOperation): """ - Round numeric values to a specified decimal precision. + Round numeric values to `precision` decimal places. Precision follows Python's built-in `round` behavior. Precision must be a non-negative integer. diff --git a/src/harmonization_framework/primitives/scale.py b/src/harmonization_framework/primitives/scale.py index 6aebd84..bc6f70e 100644 --- a/src/harmonization_framework/primitives/scale.py +++ b/src/harmonization_framework/primitives/scale.py @@ -3,7 +3,7 @@ class Scale(PrimitiveOperation): """ - Operator that applies a scaling factor to a numerical value. + Multiply numeric values by `scaling_factor` (number). """ def __init__(self, scaling_factor: Union[int, float]): if not isinstance(scaling_factor, (int, float)): diff --git a/src/harmonization_framework/primitives/substitute.py b/src/harmonization_framework/primitives/substitute.py index dfe3424..4c4eff7 100644 --- a/src/harmonization_framework/primitives/substitute.py +++ b/src/harmonization_framework/primitives/substitute.py @@ -3,7 +3,8 @@ class Substitute(PrimitiveOperation): """ - Apply a text substitution based on a regex pattern. + Replace every match of the regex `expression` with `substitution` in + string values. """ def __init__(self, expression: str, substitution: str): """ diff --git a/src/harmonization_framework/primitives/threshold.py b/src/harmonization_framework/primitives/threshold.py index b565a6d..8cf9a8c 100644 --- a/src/harmonization_framework/primitives/threshold.py +++ b/src/harmonization_framework/primitives/threshold.py @@ -3,7 +3,8 @@ class Threshold(PrimitiveOperation): """ - Operator that thresholds a numerical value. + Clamp numeric values to the inclusive range [`lower`, `upper`]: values + below `lower` become `lower`, values above `upper` become `upper`. """ def __init__(self, lower: Union[int, float], upper: Union[int, float]): if not isinstance(lower, (int, float)) or not isinstance(upper, (int, float)): diff --git a/src/harmonization_framework/primitives/truncate.py b/src/harmonization_framework/primitives/truncate.py index af42744..da2456d 100644 --- a/src/harmonization_framework/primitives/truncate.py +++ b/src/harmonization_framework/primitives/truncate.py @@ -2,7 +2,7 @@ class Truncate(PrimitiveOperation): """ - Operator that truncates a string by cutting off the tail. + Shorten strings to at most `length` characters by cutting off the tail. """ def __init__(self, length: int): if not isinstance(length, int): diff --git a/src/harmonization_framework/primitives/units.py b/src/harmonization_framework/primitives/units.py index d152747..c72fac9 100644 --- a/src/harmonization_framework/primitives/units.py +++ b/src/harmonization_framework/primitives/units.py @@ -32,9 +32,11 @@ def __init__(self, value): class ConvertUnits(PrimitiveOperation): """ - Convert numeric values between units using `pint`. + Convert numeric values from `source_unit` to `target_unit` — for example + `inch` to `cm`, or `kilogram` to `pound`. - Supports built-in `Unit` enum values or custom unit strings recognized by pint. + Units are built-in `Unit` enum values or any unit string recognized by + the `pint` library. """ def __init__(self, source: Union[Unit, str], target: Union[Unit, str]): if isinstance(source, str): diff --git a/src/harmonization_framework/primitives/validate_pattern.py b/src/harmonization_framework/primitives/validate_pattern.py index 8b369a7..7f07b4c 100644 --- a/src/harmonization_framework/primitives/validate_pattern.py +++ b/src/harmonization_framework/primitives/validate_pattern.py @@ -10,7 +10,8 @@ class ValidatePattern(PrimitiveOperation): """ - Assert that a string matches a regex pattern. + Assert that string values match the regex `expression`, using `mode` + `match` (default), `fullmatch`, or `search`. Returns the original value on success. On failure: raises `ValueError` if `strict=True`, else returns `default`. Use as a data-quality gate in diff --git a/tests/test_list_operations.py b/tests/test_list_operations.py index e777fbf..5809e4a 100644 --- a/tests/test_list_operations.py +++ b/tests/test_list_operations.py @@ -20,7 +20,7 @@ def test_cli_list_operations(capsys): for name in OPERATION_CLASSES: assert f"\n{name}\n" in f"\n{out}" # Spot-check that help text accompanies the names. - assert "Convert numeric values between units" in out + assert "Convert numeric values from `source_unit` to `target_unit`" in out def test_cli_list_operations_json(capsys):