Repository navigation
feat(analytic-registry): routine declaration + bindings, AnalyticFunctionSpec as its view (RS-W2-2 PR-A) - #546
Merged
dwolfson merged 1 commit intoNov 7, 2026
Conversation
…tionSpec as its view (RS-W2-2 PR-A) A registry entry is now readable as a RoutineDeclaration (data) plus Bindings (python | egeria_query | sql | step), mirroring trellis-analytics 0.4's trellis_analytics.routine field for field (decision D2). AnalyticFunctionSpec is the compatibility view: `function` is the one python binding; it gains the declaration's optional fields (bindings, inputs, constants, in, pushdown, tile_safe, test_only; AnalyticParam.category) so routine()/from_routine() round-trip. get_routine_registry() converts every entry mechanically and names any entry that breaks a declaration rule in routine_declaration_errors() instead of raising. AnalyticDeclaration.out accepts the library's three forms (field list, shape name, inline shape) and None, read through out_fields() (RS-W2-1a read-back F2). The module allow-list is stated as python_binding_allowed(target): it applies to binding targets only; a report spec still names routines by registered name (ISSUE-173). An entry with no python binding is refused by name when run. growth_series drops a binding_note that repeated its type_map description: a generic routine declares no note (library rule). Nothing renders it. No behaviour change: all 23 analytic demo specs give byte-identical exec_report_spec output (DICT and JSON) before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
dwolfson
added a commit
to dwolfson/egeria-python
that referenced
this pull request
Nov 8, 2026
Release 6.2.25 carries odpi#546 (RS-W2-2 PR-A: routine declaration + bindings, AnalyticFunctionSpec as its view), odpi#548 (RS-W2-2 PR-B: resolve every report spec at load; list unrunnable specs with words) and odpi#549 (Dr.Egeria: cache Egeria 404-002 ambiguous lookups; skip the display-name pre-check for action commands). Micro-tests on 3.13: 2240 collected, 0 failed. Wheel checked in a clean venv (my_egeria top-level, serve_my_profile installed). Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
dwolfson
added a commit
that referenced
this pull request
Nov 8, 2026
Release 6.2.25 carries #546 (RS-W2-2 PR-A: routine declaration + bindings, AnalyticFunctionSpec as its view), #548 (RS-W2-2 PR-B: resolve every report spec at load; list unrunnable specs with words) and #549 (Dr.Egeria: cache Egeria 404-002 ambiguous lookups; skip the display-name pre-check for action commands). Micro-tests on 3.13: 2240 collected, 0 failed. Wheel checked in a clean venv (my_egeria top-level, serve_my_profile installed). Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
dwolfson
added a commit
that referenced
this pull request
Nov 8, 2026
Release 6.2.25 carries #546 (RS-W2-2 PR-A: routine declaration + bindings, AnalyticFunctionSpec as its view), #548 (RS-W2-2 PR-B: resolve every report spec at load; list unrunnable specs with words) and #549 (Dr.Egeria: cache Egeria 404-002 ambiguous lookups; skip the display-name pre-check for action commands). Micro-tests on 3.13: 2240 collected, 0 failed. Wheel checked in a clean venv (my_egeria top-level, serve_my_profile installed). Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RS-W2-2 PR-A (Wave 2 delivery step (a″), first of three): the routine declaration and bindings as a model, with no behaviour change. A registry entry is now readable as a
RoutineDeclaration(data) plusBindings (how it is reached), andAnalyticFunctionSpecis the compatibility view of one: itsfunctionis the one python binding. Decision D2 applied: the schema mirrors egeria-trellis-analytics 0.4'strellis_analytics.routinefield for field, and a cross-validation test loads every pyegeria built-in in the library. The resolver (PR-B) and the parameter rules (PR-C) are not in this PR.Model (
pyegeria/view/analytic_registry.py)extra="forbid"), same names and rules as the library:RoutineDeclaration,ParamDeclaration(category: content | shape | performance),Binding(python | egeria_query | sql | step),TileSafety,Admission; vocabulariesROUTINE_KINDS,BINDING_KINDS,PARAM_CATEGORIES,INPUT_ROLES. The refusals are the library's sentences: a constant that is also a param, a required param with a default, two python bindings, a non-role input,inon anything but a processor, a generic routine with a binding_note, a tile cap withsafefalse, no tile reason.RoutineDeclaration.declarationis the W2-1aAnalyticDeclaration;outlives there, as in the library.AnalyticFunctionSpecis the view. It gains the declaration's own fields, all optional, so it carries a declaration whole:bindings,inputs,constants,in(attributein_),pushdown,tile_safe,test_only(withresource_types, theAdmission);AnalyticParamgainscategory(defaultcontent);kindwidens to producer | processor | routine | step.functionand the python binding are one value: either fills the other, and two that differ, two python bindings, or no binding at all are refused.functionmay now be empty for an entry with only non-python bindings.spec.routine()/AnalyticFunctionSpec.from_routine(routine, returns=, action=, envelope=)convert both ways;returns,actionandenvelopeare the view's own fields, which a declaration doesn't carry.get_routine_registry()converts every registry entry mechanically (built-in, config, installed, runtime). An entry that breaks a declaration rule is left out and named, with the rule's words, byroutine_declaration_errors(). It still runs as before, so a third-party entry can't stop loading because of this PR.declaration.outaccepts the library's three forms (RS-W2-1a read-back F2): a field list, a registered shape name, or an inline shape. It also acceptsNone, the library's word for "not declared". Read it through the newAnalyticDeclaration.out_fields(). A shape name only the library registers, and an inline shape's reused fields (extends/include), read as[]here; PR-B's check 3 says why.The allow-list applies to binding targets only (ISSUE-173)
format_set_executor.python_binding_allowed(target)is the module allow-list, stated as a check on a python binding's target._resolve_analytic_functionresolves a registered name to the entry's python binding. An entry with no python binding is refused by name, for exampleAnalytic function 'saved_census' has no python binding (its bindings: egeria_query 'Census query'); this pyegeria runs python bindings only.That path couldn't exist before. Its other two cases, a path a registered entry declares and a path under an allowed prefix, are unchanged. They are binding targets (action fetch/analytic steps, binder factories), never report-spec strings:resolve_report_spec_functionalready accepts registered names only. A test pins that a dotted path under an allowed prefix is still refused from a report spec.One data change:
growth_series.binding_notegrowth_seriesis generic and carried a binding_note ("type_map defaults to assets/terms/governed/products but is fully overridable."). The library refuses that combination, because a note names what is fixed and a generic routine fixes nothing. The note repeated thetype_mapparam's own description, so it is now empty. Nothing renders it:_demo()uses the note only whengenericis false, and the demo spec is byte-identical. It still shows inanalytic_registry_payload().Gates (brief §3, PR-A)
uv run -p 3.13 pytest tests/micro-tests/gives 2204 passed, 3 skipped (2207 collected). The 3 skips are the two library cross-validation modules, skipped because the library isn't a dependency, and one pre-existing skip. No existing test was edited.feat/declared-shapes-0.4branch, 549d565; scratch venv, Python 3.13, editable pyegeria from this branch): the whole micro-suite gives 2329 passed, 1 skipped (2330 collected), including 99 cross-validation tests acrosstest_routine_declarations_match_library.pyand W2-1a'stest_declarations_match_library.py. The registry has 31 entries: 28 built-in and 3 from the library (curation_coverage,context_pack,curation_coverage_tile). All 31 convert, androutine_declaration_errors()is{}. That run found that the library writes an undeclaredoutasNone, which the first cut refused; it is accepted now and tested.exec_report_specbyte-identical on the demo specs: all 23 analytic demo specs, in DICT and JSON (46 runs), with a fake client that exercises every routine. I wrote the JSON of every result, plus each spec'smodel_dumpand each registry entry's function, before (upstream/main 48392e6) and after;diffshows no difference. Two runs of the baseline were identical, so the comparison is deterministic.spec → routine() → from_routine → model_dumpequal to the original (28 tests). A declaration that uses every field (processor within, inputs, constants, three param categories, tile cap, admission, an egeria_query and a python binding) goes declaration → view → declaration equal, and throughmodel_dump/model_validateby name and by alias.test_routine_declarations_match_library.py, skipped without library 0.4): every built-in's routine loads as a libraryRoutineDeclaration, with noDeprecationWarningreaching it. The library's own reading of each pyegeria entry (routine_declaration(spec)) equals pyegeria'sspec.routine(). Model field names and the four vocabularies match the library's exactly.Not in this PR
contentby default. Choosing shape or performance per param, such as page caps orstrict, is judgment that PR-C's four rules depend on, so it belongs with PR-C, or a follow-up if the Architect prefers.inputs,constants,pushdownandtile_safeare empty on every built-in. The model carries them; authoring them is W2-3 (roles) and PR-C (constants).runnable/unrunnable_reason), PR-C (parameter rules, D3), and the executor readingtarget_type_name: per the brief, those are PR-B and PR-C.ruffis clean on every new and changed line. The 4 findings informat_set_executor.py(unusedjson, three unusede) are already on upstream/main.No version bump, no tag. No Egeria, Postgres or 8813 writes.
🤖 Generated with Claude Code