dpmcore.services.scope_calculator
Resolve the data-point scopes and module versions touched by a DPM-XL expression.
ScopeCalculatorService
- class dpmcore.services.scope_calculator.ScopeCalculatorService(session)[source]
Bases:
objectCalculate operation scopes for DPM-XL expressions.
Determines which module versions are involved in an operation based on table references and precondition items.
- Parameters:
session (
Session) – An open SQLAlchemy session.
- __init__(session)[source]
Build the service bound to
session.- Parameters:
session (Session)
- Return type:
None
- calculate_from_expression(expression, release_id=None, precondition_items=None, release_code=None, *, precondition_expression=None)[source]
Calculate scopes for expression, optionally gated.
Parses the expression, runs OperandsChecking to extract table codes, then delegates to
OperationScopeService.precondition_itemsis the list of precondition variable codes that gate the validation; passNoneor[]if the validation has no preconditions.When
precondition_expressionis supplied, the gate’s own operands join the resolution by their matching channels — its table codes are unioned intotable_codesand its mandatory precondition variable codes intoprecondition_items(unioned with any the caller passed). The two are not interchangeable: onlytable_codesresolves throughget_from_table_codes, and onlyprecondition_itemsgets the filing-indicator filter and the1-14check. Because a module hosts an intra-module scope only when it supplies every operand, a gate reaching outside the expression’s own modules widens the scope to cross-module, or empties it — which is the honest verdict, since the pair is only evaluable where both halves resolve. That change is reported inwarning, and a gate-attributable failure setserror_sourceto"precondition"with a prefixed message.The two channels treat a disjunctive gate differently, deliberately. Variable codes are intersected across
orbranches, so an optional filing indicator does not constrain scope. Table codes come from the gate’sOperandsCheckingpass, which does not model boolean structure, so every table the gate mentions is required even when only one branch needs it. That errs toward reporting a wider scope rather than missing a table the pair genuinely needs, and costs nothing on the real dictionary, where no persisted precondition references a table.Passing no
precondition_expressioncosts nothing: no second scope resolution, no warning, and byte-identical error messages.- Parameters:
expression (
str) – The DPM-XL expression to scope.precondition_items (
Optional[List[str]]) – Filing-indicator codes gating the validation.release_code (
Optional[str]) – Optional release code (mutually exclusive withrelease_id).precondition_expression (
Optional[str]) – Optional DPM-XL gate expression. Keyword-only, matchingSemanticService.validate, so the pre-existing positional arguments keep their meaning.
- Return type:
- calculate_from_tables(table_vids, precondition_items=None, release_id=None, table_codes=None, release_code=None)[source]
Calculate scopes directly from table version IDs.
- filter_valid_dependency_modules(scope_result, primary_module_vid)[source]
Return module VIDs that co-occur with primary_module_vid.
Only modules that actually appear alongside the primary module in a multi-module scope are valid cross-module partners. This filters out sibling modules that share tables but are not actual cross-module dependencies.
- Return type:
- Parameters:
scope_result (ScopeResult)
primary_module_vid (int)
- detect_cross_module_dependencies(scope_result, primary_module_vid, operation_code=None, release_id=None, time_shifts=None, compute_alternative_deps=True, release_code=None, referenced_variables=None, referenced_tables=None, home_module_tables=None)[source]
Build dependency information for a scope result.
- Parameters:
scope_result (
ScopeResult) – The computed scope result.primary_module_vid (
int) – VID of the primary module.operation_code (
Optional[str]) – Current operation code (if any).time_shifts (
Optional[Dict[str,str]]) – Optional mapping of table codes to ref-period strings (e.g.{"C_01.00": "T-1Q"}). Tables not present default to"T".compute_alternative_deps (
bool) – When True (default) the returnedalternative_dependenciesis populated from this singlescope_result. Aggregating callers that compute alternatives across many scope results should passFalseto avoid the per-call work.release_code (
Optional[str]) – Optional release code; resolved torelease_idviaRelease.code. Mutually exclusive withrelease_id.referenced_variables (
Optional[Dict[str,str]]) – Optional{datapoint: type_code}of every operand datapoint the operation references, across all modules it spans — home module included. Declared in each dependency module’svariablesmap (#251).referenced_tables (
Optional[Set[str]]) – Optional table codes the operation references. Together withreferenced_variablesthis narrows each dependency module’s declaration to the subset the operation uses (#250); omit both to declare the dependency modules whole.home_module_tables (
Optional[Set[str]]) – Optional pre-computed set of table codes owned by the primary (home) module — the same set this method would derive from_get_module_tables(). Callers that iterate this method with a fixedprimary_module_vid(per-op dependency detection over a script’s operations) should pass a single pre-computed set to avoid re-running the per-table variable/open-key fetch on every iteration.
- Return type:
Returns a dict with: -
intra_instance_validations-cross_instance_dependencies-alternative_dependencies-dependency_modules
- detect_alternative_dependencies(scope_results, primary_module_vid, release_id=None, release_code=None, valid_module_uris=None)[source]
Detect disjoint groups of interchangeable external modules.
Two external modules are alternatives only when they are interchangeable dependencies of the same operation (#202): within a single operation’s scopes they each appear as the sole external module alongside the primary, yet never co-exist in one scope. Each
ScopeResultis one operation, so candidate pairs are collected per scope result — being the sole external of two different operations does not make two modules alternatives.Interchangeable pairs are then collapsed into disjoint groups so that when three or more modules are mutually interchangeable they surface as one group rather than every overlapping pair (#242).
- Parameters:
scope_results (
List[ScopeResult]) – One entry per operation.primary_module_vid (
int) – VID of the primary module.release_id (
Optional[int]) – Optional release filter (validated only).release_code (
Optional[str]) – Optional release code (validated only).valid_module_uris (
Optional[Set[str]]) – When given, the genuine dependency-module URIs of the script. Pairs referencing a module outside this set are dropped soalternative_dependenciescan never name a module absent fromdependency_modules(#202 dangling references).
- Return type:
Returns a list of disjoint groups; each group is a sorted list of two or more interchangeable module URIs, and no module appears in more than one group.
ScopeResult
- class dpmcore.services.scope_calculator.ScopeResult(scopes=<factory>, total_scopes=0, is_cross_module=False, module_versions=<factory>, has_error=False, error_message=None, warning=None, error_source=None)[source]
Outcome of a scope calculation.
warningis only ever set when aprecondition_expressionchanged the computed scope.error_sourcenames the half a failure belongs to and is set wheneverhas_erroris true. Neither changeserror_messagefor a call that passes no precondition expression.- Parameters: