neuralqx.utils.parsing module

This file contains implementation of parsing related helper functions

required_kwargs(*required_args, conditional_args=None)

Decorator enforcing the presence of required keyword arguments.

The returned decorator validates that specified keyword arguments are provided when the decorated function is called. It supports:

  • unconditional requirements: names listed in required_args must always appear in kwargs

  • conditional requirements: extra required kwargs depending on the value of another kwarg

Conditional requirements are specified as:

conditional_args = {
    "<condition_key>": {
        "<condition_value_1>": ["req_kw_1", "req_kw_2", ...],
        "<condition_value_2>": [...],
    },
    ...
}

If condition_key is present in kwargs and its value matches one of the configured condition_value entries, then the corresponding list of required kwargs must also be present.

Parameters:
  • required_args – Names of keyword arguments that must always be present.

  • conditional_args – Optional mapping {condition_key: {condition_value: [required_kw, ...]}} defining conditional requirements.

Returns:

A decorator that wraps the target function and raises ValueError when required kwargs are missing.

Raises:

ValueError – When any unconditional or conditional required keyword argument is missing.

log_module_attributes(solver, module, prefix='')

Recursively log attributes of a Flax module into the solver logger.

This function iterates over the public attributes of a Flax linen.Module instance and logs each attribute into the solver’s logger under the “Network Configs” section. For nested module attributes, it recurses to capture the full hierarchy.

Wrapper modules:

If module has an attribute base that is itself a Flax module (a common wrapper pattern), the attributes of module.base are also logged under the <prefix>.base namespace.

Logging details: - The logger is retrieved as solver.logger if available, otherwise solver._logger. - Attributes starting with "_" and the attribute named "name" are skipped. - Values are converted to readable strings using get_attr_val().

Parameters:
  • solver – Object providing a logger via solver.logger or solver._logger.

  • module – Flax module instance whose attributes should be logged.

  • prefix – Optional namespace prefix for the logged attribute names. If empty, the module class name is used.

Returns:

None.

get_attr_val(attr)

Return a robust string representation for an attribute value.

This helper is designed for logging configuration-like objects where naïve str(attr) may fail or be uninformative. It handles:

  • Flax linen.Module instances (returns the class name)

  • Python modules (returns "Module '<name>'")

  • Classes (returns the class name when available)

  • Common containers (lists/tuples/dicts), recursively formatting their contents

  • functools.partial (returns "partial(<funcname>)")

  • Generic callables without __name__ (returns a best-effort type/name)

  • Fallback to str(attr), with a safe type-based fallback if string conversion fails

Parameters:

attr – Attribute value to stringify.

Return type:

str

Returns:

A human-readable string representation suitable for logs.

str_edge_parser(s)

Parse an edge represented as a string into a Python tuple.

The input must be a string that looks like a tuple (starts with "(" and ends with ")"). The contents are parsed with ast.literal_eval() for safety.

Expected formats: - Planar graphs: a tuple of integers (a, b) - Non-planar graphs (coordinate vertices): a tuple of tuples

((a, b, c), (d, e, f)) describing the coordinates of the two vertices.

Parameters:

s (str) – String representation of an edge tuple.

Return type:

Union[tuple[int, int], tuple[int, int, int]]

Returns:

Parsed tuple representing the edge.

Raises:

ValueError – If the string is not tuple-like, cannot be parsed, or does not evaluate to a Python tuple.

calculate_total_terms(current_level_terms)

Compute the total number of term entries across all vertices/triplets for a TRC level.

The input is expected to be a dictionary keyed by vertex (or similar identifiers) whose values contain a "triplets" list. Each triplet entry is expected to have a "terms" field that is a list of term objects. The total is the sum of len(triplet["terms"]) over all triplets in the structure.

Parameters:

current_level_terms (dict) – Nested contributions structure containing triplets and their term lists.

Return type:

int

Returns:

Total number of terms across all triplets in all contributions.

Raises:
  • KeyError – If the expected keys ("triplets" / "terms") are missing.

  • TypeError – If the values do not have the expected container structure.

strict_type(obj)

Return the “semantic base class” of an object whose runtime type may be a parameterised Generic specialization.

This helper is meant for libraries that use typing.Generic and produce runtime-generated subclasses with names like Foo[Bar] (for example, lazy-operator wrappers or generic specializations). In such cases, type(obj) is not the unparameterised class Foo, but a distinct dynamically-created subclass whose __name__ contains [...].

The function attempts to map such a specialised runtime class back to its corresponding unparameterised base class by:

  1. Taking the runtime class cls (or using the input directly if it is a class).

  2. If cls.__name__ does not contain '[', returning cls unchanged.

  3. Otherwise, extracting the base name before the bracket (e.g. "Foo" from "Foo[Bar]").

  4. Walking the method resolution order (MRO) and returning the first base class whose __name__ matches that

    extracted base name.

If no matching base class name is found in the MRO, the function falls back to returning cls.

Notes: - This is a pragmatic runtime-introspection utility. It relies on the naming convention BaseName[...] and may

not apply to all generic implementations.

Examples

>>> type(op)
<class 'mypkg.Foo[Bar]'>
>>> strict_type(op)
<class 'mypkg.Foo'>
>>> strict_type(op) is mypkg.Foo
True