Skip to content

Conversation

@xaled
Copy link
Contributor

@xaled xaled commented May 23, 2025

Hi,

While working on an SPL command for a Splunk add-on that evaluates Python expressions to process event fields and create new ones, I ran into some limitations with simpleeval. I made a few changes to support my needs:

  • Flattening attribute chains: Splunk flattens JSON and uses keys like uri.params. I wanted to use dot notation (uri.params) instead of log['uri.params'] for convenience and readability.
  • Assignment support: The command should be able to assign values to new or existing fields, like:
    ... | evalp parsed_url = urlparse(http.uri)
  • Multiple expressions: I needed to support multiple expressions in one command, like:
    ... | evalp http.uri = extract_url(http.full_request); http.parsed_uri = parseurl(http.query)

These features are off by default, so they won't affect existing behavior. They’re mostly useful for my use case, but feel free to include them if you think they’d be helpful.

Thanks!

Description

Assignment Support

If you want to allow modification of the names dictionary using assignment or augmented assignment (=, +=, etc.), set assign_modify_names=True.

>>> names = dict()
>>> simple_eval("a = 10 * 2", names=names, assign_modify_names=True)
>>> print(names['a'])
20

>>> names = dict(a=10)
>>> simple_eval("a += 5", names=names, assign_modify_names=True)
>>> print(names['a'])
15

When using the SimpleEval class, updated values are available in the .results attribute:

>>> s = SimpleEval(names=dict(a=10, b=5), assign_modify_names=True)
>>> s.eval("b += a")
>>> print(s.results)
{'b': 15}

Note: Assignment to attributes (e.g., a.b = 1) or tuples (e.g., a, b = (1, 2)) is not supported.

Multiple Expressions

By default, only the first expression is evaluated. To evaluate multiple expressions separated by ; or newlines and return the last expression's result, set multiple_expression_support=True.

>>> simple_eval("5 * 2; 6 * 2", multiple_expression_support=False)
10

>>> simple_eval("5 * 2\n 6 * 2", multiple_expression_support=True)
12

Combined with assignment:

>>> simple_eval("a=5;b=2;a + b", multiple_expression_support=True)
7

Attribute Chain Flattening

If attr_chain_flattening=True, then attributes can be treated as flat keys in names.

>>> simple_eval("a + a.b", names={"a": 1, "a.b": 2}, attr_chain_flattening=True)
3

If both a flat key and an actual attribute exist, the flat key takes precedence:

>>> from types import SimpleNamespace
>>> simple_eval("a.attr", names={"a": SimpleNamespace(attr=True), "a.attr": False}, attr_chain_flattening=True)
False

With assignment enabled, only flat keys are written, as attribute assignment is unsupported:

>>> from types import SimpleNamespace
>>> names = {"a": SimpleNamespace(b=1)}
>>> simple_eval("a.b = 10", names=names, attr_chain_flattening=True, assign_modify_names=True)
>>> print(names['a.b'])
10
>>> print(names['a'].b)
1

Pre-approval checklist (for submitter)

Please complete these steps

  • Passes tests
  • New tests for additional features or changed functionality
  • My name and contribution added to contributors list (or if I'd rather opt out, I've said so in the PR)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant