uneval


Nameuneval JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryLibrary for generating python-expressions
upload_time2024-08-26 11:36:06
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseApache License 2.0
keywords expression ast dsl fexpr lambda symbolic
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # UnEval #

UnEval is a microlibrary for generating python-expressions.

If you ever need to use
[eval](https://docs.python.org/3/library/functions.html#eval),
write [macros](https://en.wikipedia.org/wiki/Macro)
or implement [domain specific languages](https://en.wikipedia.org/wiki/Domain-specific_language),
this library provides a better way to generate python expressions than using [strings](https://docs.python.org/3/library/stdtypes.html#str).
Strings can contain syntax errors, make it harder to deal with parentheses and aren't syntax highlighted.
Expressions look and act a lot like pythoncode, except that they aren't evaluated immediately.

## Installation ##

Make sure to [install pip](https://pip.pypa.io/en/stable/installation/) then run:
```sh
pip install uneval
```

## Usage ##

Firstly, the building blocks can be used to generate expressions.
Secondly, these expressions can be converted.

### Examples ###

```python
import ast
from uneval import quote, to_ast, to_bytecode

# Build expressions
x, y = quote.x, quote.y  # Shortcut for quote("x"), quote("y")
z = x * x + y * y

# Convert
print(z)  # x * x + y * y
print(ast.dump(to_ast(z)))  # BinOp(left=BinOp(left=Name(id='x', ctx=Load()), op=Mult(), right=Name(id='x', ctx=Load())), op=Add(), right=BinOp(left=Name(id='y', ctx=Load()), op=Mult(), right=Name(id='y', ctx=Load())))
print(eval(to_bytecode(z), {"x": 3, "y": 4}))  # 25
```

This can be used when working in [pandas](https://pandas.pydata.org/) and you want to use [eval](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.eval.html#pandas.DataFrame.eval) or [query](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html#pandas.DataFrame.query):

```python
from uneval import quote as q

# No syntax highlighting. Syntax checkers won't catch errors.
df.eval("bmi = mass / height**2")

# With syntax highlighting. Syntax checkers can catch errors here.
df.eval(f"bmi = {q.mass / q.height**2}")
```

Expressions can also be converted to [λ](https://docs.python.org/3/glossary.html#term-lambda)-functions:

```python
from uneval import F, quote

x, y = quote.x, quote.y

hello = F("Hello World!")
hello()  # => "Hello World!"

plus1 = F.x(x + 1)
plus1(4)  # => 5

multiply = F.xy(x * y)
multiply(5, 7)  # => 35
```

### Building blocks ###

```python
from uneval import quote as q
```

| Factory       | Example                                             | Result                       |
|---------------|-----------------------------------------------------|------------------------------|
| `quote`       | `q('a')` or `q.a` (shortcut)                        | `a`                          |
| `if_`         | `if_(q.x >= 0, q.x, -q.x)`                          | `x if x >= 0 else -x`        |
| `for_`        | `for_(q.x**2, (q.x, q.range(5)))`                   | `(x**2 for x in range(5))`   |
| `lambda_`     | `lambda_([q.x], q.x * q.x)`                         | `lambda x: x * x`            |
| `and_`, `or_` | `and_(q.x >= 10, q.x <= 15)`                        | `x >= 10 and x <= 15`        |
| `not_`, `in_` | `not_(in_(q.x, {1, 2, 3}))`                         | `not x in {1, 2, 3}`         |
| `fstr`, `fmt` | `fstr("sin(", q.a, ") is ", fmt(q.sin(q.a), ".3"))` | `f'sin({a}) is {sin(a):.3}'` |

### Converters ###

| Converter      | Target      | Remark                     |
|----------------|-------------|----------------------------|
| `str`          | String      | Convert to readable python |
| `to_ast`       | AST-node    | Convert to AST-node        |
| `to_bytecode`  | Code-object | Compile the expression     |
| `F.parameters` | Function    | Create a λ-function        |

## Similar work ##

Libraries that implement something similar:
- [Macropy](https://github.com/lihaoyi/macropy) has [quasiquote](https://macropy3.readthedocs.io/en/latest/reference.html#quasiquote).
- [SymPy](https://www.sympy.org/en/index.html) - Symbolic manipulation, but its representation is different from Python.
- [Polars](https://docs.pola.rs/user-guide/expressions/) - Writing `col.x` creates something like this `Expression`-object.

Other:
- [Fixing lambda](https://stupidpythonideas.blogspot.com/2014/02/fixing-lambda.html) - A blog post about alternative lambda syntaxes.
- [Mini-lambda](https://smarie.github.io/python-mini-lambda/#see-also) - Packages to "fix" lambda.
- [Meta](https://srossross.github.io/Meta/html/) - A few utils to work on AST's.
- [latexify](https://github.com/google/latexify_py) and [pytexit](https://github.com/erwanp/pytexit) - Convert python to LaTeX.
- [numexpr](https://github.com/pydata/numexpr) and [aesara](https://github.com/aesara-devs/aesara) / [pytensor](https://github.com/pymc-devs/pytensor) - Fast evaluation of numerical expressions.

Useful references:
- [python macros use cases](https://stackoverflow.com/questions/764412/python-macros-use-cases) - Stack-overflow discussion.
- [Green tree snakes](https://greentreesnakes.readthedocs.io/en/latest/) - Unofficial documentation of AST nodes.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "uneval",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "expression, ast, dsl, fexpr, lambda, symbolic",
    "author": null,
    "author_email": "lverweijen <lauwerund@gmail.com>",
    "download_url": null,
    "platform": null,
    "description": "# UnEval #\r\n\r\nUnEval is a microlibrary for generating python-expressions.\r\n\r\nIf you ever need to use\r\n[eval](https://docs.python.org/3/library/functions.html#eval),\r\nwrite [macros](https://en.wikipedia.org/wiki/Macro)\r\nor implement [domain specific languages](https://en.wikipedia.org/wiki/Domain-specific_language),\r\nthis library provides a better way to generate python expressions than using [strings](https://docs.python.org/3/library/stdtypes.html#str).\r\nStrings can contain syntax errors, make it harder to deal with parentheses and aren't syntax highlighted.\r\nExpressions look and act a lot like pythoncode, except that they aren't evaluated immediately.\r\n\r\n## Installation ##\r\n\r\nMake sure to [install pip](https://pip.pypa.io/en/stable/installation/) then run:\r\n```sh\r\npip install uneval\r\n```\r\n\r\n## Usage ##\r\n\r\nFirstly, the building blocks can be used to generate expressions.\r\nSecondly, these expressions can be converted.\r\n\r\n### Examples ###\r\n\r\n```python\r\nimport ast\r\nfrom uneval import quote, to_ast, to_bytecode\r\n\r\n# Build expressions\r\nx, y = quote.x, quote.y  # Shortcut for quote(\"x\"), quote(\"y\")\r\nz = x * x + y * y\r\n\r\n# Convert\r\nprint(z)  # x * x + y * y\r\nprint(ast.dump(to_ast(z)))  # BinOp(left=BinOp(left=Name(id='x', ctx=Load()), op=Mult(), right=Name(id='x', ctx=Load())), op=Add(), right=BinOp(left=Name(id='y', ctx=Load()), op=Mult(), right=Name(id='y', ctx=Load())))\r\nprint(eval(to_bytecode(z), {\"x\": 3, \"y\": 4}))  # 25\r\n```\r\n\r\nThis can be used when working in [pandas](https://pandas.pydata.org/) and you want to use [eval](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.eval.html#pandas.DataFrame.eval) or [query](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html#pandas.DataFrame.query):\r\n\r\n```python\r\nfrom uneval import quote as q\r\n\r\n# No syntax highlighting. Syntax checkers won't catch errors.\r\ndf.eval(\"bmi = mass / height**2\")\r\n\r\n# With syntax highlighting. Syntax checkers can catch errors here.\r\ndf.eval(f\"bmi = {q.mass / q.height**2}\")\r\n```\r\n\r\nExpressions can also be converted to [\u03bb](https://docs.python.org/3/glossary.html#term-lambda)-functions:\r\n\r\n```python\r\nfrom uneval import F, quote\r\n\r\nx, y = quote.x, quote.y\r\n\r\nhello = F(\"Hello World!\")\r\nhello()  # => \"Hello World!\"\r\n\r\nplus1 = F.x(x + 1)\r\nplus1(4)  # => 5\r\n\r\nmultiply = F.xy(x * y)\r\nmultiply(5, 7)  # => 35\r\n```\r\n\r\n### Building blocks ###\r\n\r\n```python\r\nfrom uneval import quote as q\r\n```\r\n\r\n| Factory       | Example                                             | Result                       |\r\n|---------------|-----------------------------------------------------|------------------------------|\r\n| `quote`       | `q('a')` or `q.a` (shortcut)                        | `a`                          |\r\n| `if_`         | `if_(q.x >= 0, q.x, -q.x)`                          | `x if x >= 0 else -x`        |\r\n| `for_`        | `for_(q.x**2, (q.x, q.range(5)))`                   | `(x**2 for x in range(5))`   |\r\n| `lambda_`     | `lambda_([q.x], q.x * q.x)`                         | `lambda x: x * x`            |\r\n| `and_`, `or_` | `and_(q.x >= 10, q.x <= 15)`                        | `x >= 10 and x <= 15`        |\r\n| `not_`, `in_` | `not_(in_(q.x, {1, 2, 3}))`                         | `not x in {1, 2, 3}`         |\r\n| `fstr`, `fmt` | `fstr(\"sin(\", q.a, \") is \", fmt(q.sin(q.a), \".3\"))` | `f'sin({a}) is {sin(a):.3}'` |\r\n\r\n### Converters ###\r\n\r\n| Converter      | Target      | Remark                     |\r\n|----------------|-------------|----------------------------|\r\n| `str`          | String      | Convert to readable python |\r\n| `to_ast`       | AST-node    | Convert to AST-node        |\r\n| `to_bytecode`  | Code-object | Compile the expression     |\r\n| `F.parameters` | Function    | Create a \u03bb-function        |\r\n\r\n## Similar work ##\r\n\r\nLibraries that implement something similar:\r\n- [Macropy](https://github.com/lihaoyi/macropy) has [quasiquote](https://macropy3.readthedocs.io/en/latest/reference.html#quasiquote).\r\n- [SymPy](https://www.sympy.org/en/index.html) - Symbolic manipulation, but its representation is different from Python.\r\n- [Polars](https://docs.pola.rs/user-guide/expressions/) - Writing `col.x` creates something like this `Expression`-object.\r\n\r\nOther:\r\n- [Fixing lambda](https://stupidpythonideas.blogspot.com/2014/02/fixing-lambda.html) - A blog post about alternative lambda syntaxes.\r\n- [Mini-lambda](https://smarie.github.io/python-mini-lambda/#see-also) - Packages to \"fix\" lambda.\r\n- [Meta](https://srossross.github.io/Meta/html/) - A few utils to work on AST's.\r\n- [latexify](https://github.com/google/latexify_py) and [pytexit](https://github.com/erwanp/pytexit) - Convert python to LaTeX.\r\n- [numexpr](https://github.com/pydata/numexpr) and [aesara](https://github.com/aesara-devs/aesara) / [pytensor](https://github.com/pymc-devs/pytensor) - Fast evaluation of numerical expressions.\r\n\r\nUseful references:\r\n- [python macros use cases](https://stackoverflow.com/questions/764412/python-macros-use-cases) - Stack-overflow discussion.\r\n- [Green tree snakes](https://greentreesnakes.readthedocs.io/en/latest/) - Unofficial documentation of AST nodes.\r\n",
    "bugtrack_url": null,
    "license": "Apache License 2.0",
    "summary": "Library for generating python-expressions",
    "version": "0.1.2",
    "project_urls": {
        "Changelog": "https://github.com/lverweijen/python-uneval/blob/main/changes.md",
        "Homepage": "https://github.com/lverweijen/python-uneval",
        "Issues": "https://github.com/lverweijen/python-uneval/issues",
        "Pypi": "https://github.com/lverweijen/python-uneval",
        "Repository": "https://github.com/lverweijen/python-uneval"
    },
    "split_keywords": [
        "expression",
        " ast",
        " dsl",
        " fexpr",
        " lambda",
        " symbolic"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "10199bec16f4f38d41c5f5edf6578064842dfea8ade6aaad0357bde0b0656918",
                "md5": "5dedc033303094c6406bc35003789eee",
                "sha256": "2b00b0a8b807e00194b00ee8ebc2f6f70373608ee76a7bbb19e422e74b9d9d03"
            },
            "downloads": -1,
            "filename": "uneval-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5dedc033303094c6406bc35003789eee",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 12389,
            "upload_time": "2024-08-26T11:36:06",
            "upload_time_iso_8601": "2024-08-26T11:36:06.080525Z",
            "url": "https://files.pythonhosted.org/packages/10/19/9bec16f4f38d41c5f5edf6578064842dfea8ade6aaad0357bde0b0656918/uneval-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-26 11:36:06",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lverweijen",
    "github_project": "python-uneval",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "uneval"
}
        
Elapsed time: 2.22378s