dicteval-0.0.6/0000755000076500000240000000000013364255306014246 5ustar osantanastaff00000000000000dicteval-0.0.6/LICENSE0000644000076500000240000000206413263550554015256 0ustar osantanastaff00000000000000MIT License Copyright (c) 2018 Osvaldo Santana Neto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.dicteval-0.0.6/MANIFEST.in0000644000076500000240000000003313263550674016004 0ustar osantanastaff00000000000000include README.rst LICENSE dicteval-0.0.6/PKG-INFO0000644000076500000240000001355013364255306015347 0ustar osantanastaff00000000000000Metadata-Version: 1.2 Name: dicteval Version: 0.0.6 Summary: Evaluate expressions in dict/json objects Home-page: https://github.com/osantana/dicteval Author: Osvaldo Santana Neto Author-email: dicteval@osantana.me License: MIT Description: dicteval ======== Library to evaluate expressions in dict/json objects. Requirements ------------ * Python 3.6+ Basic Usage ----------- Module ``dicteval`` will evaluate basic types with no modifications but it will evaluate dicts (or json objects) containing keys started with ``=`` (equal) symbol as an expression: >>> from dicteval import dicteval >>> dicteval(3) 3 >>> dicteval([3, 5]) [3, 5] >>> dicteval((5, 3)) [5, 3] >>> dicteval({"=sum": [3, 5]}) 8 >>> dicteval({"=": 5}) # = symbol alone is a 'nop' function 5 You can provide a dictionary with context to be used during evaluation process. >>> dicteval({"=": "!{var}"}, context={"var": 1.0}) 1.0 You can also wrap your string content with ``@{}`` to force a Python ``eval()`` with the context provided: >>> dicteval({"=sum": [3, "@{var + 2}"]}, context={"var": 3}) 8 .. warning:: This functionality will be removed (or changed) in future releases for security reasons. Functions --------- You can use the following builtin functions in your expressions: Function ``=any`` ''''''''''''''''' Returns ``True`` if any element of sequence is true. >>> dicteval({"=any": [1, 2, 3]}) True >>> dicteval({"=any": [0, 0]}) False Function ``=eq`` '''''''''''''''' Returns ``True`` if all elements of sequence are equals: >>> dicteval({"=eq": [1, 1, 1, 1]}) True Function ``=if`` '''''''''''''''' Evaluates condition and returns first value if true, otherwise, returns second value. If no false value is supplied, it is assumed to be ``None``. >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 6}) 'yes' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 4}) 'no' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes"]}, context={"var": 4}) Function ``=neq`` ''''''''''''''''' Returns ``True`` if elements of sequence are different: >>> dicteval({"=neq": [1, 1, 1, 5]}) True Function ``=`` (or ``nop``) ''''''''''''''''''''''''''' Returns the same values passed as arguments: >>> dicteval({"=": [1, 2, 3, 4]}) [1, 2, 3, 4] >>> dicteval({"=nop": "spam"}) 'spam' Function ``=not`` ''''''''''''''''' Returns the boolean inverse of argument: >>> dicteval({"=not": False}) True >>> dicteval({"=not": True}) False >>> dicteval({"=not": None}) True >>> dicteval({"=not": "XYZ"}) False Function ``=sum`` ''''''''''''''''' Returns a number with the sum of arguments: >>> dicteval({"=sum": [3, 5]}) 8 Function ``=mul`` ''''''''''''''''' Returns a number with the product of arguments: >>> dicteval({"=mul": [3, 5]}) 15 Function ``=all`` ''''''''''''''''' Return True if all elements of the iterable are true (or if the iterable is empty) >>> dicteval({"=all": (True, False)}) False >>> dicteval({"=all": (True, True)}) True Function ``=divmod`` '''''''''''''''''''' Returns a tuple containing the quotient and remainder after division: >>> dicteval({"=divmod": [8,3]}) (2, 2) >>> dicteval({"=divmod": [7.5,2.5]}) (3.0, 0.0) Function ``=zip`` ''''''''''''''''' Return list of aggregate tuples constructed from elements of multiple iterables. >>> dicteval({"=zip": [[1, 2, 3], [4, 5], [6, 7, 8, 9]]}) [(1, 4, 6), (2, 5, 7)] To Do ----- - Add more functions to the builtin language Contribute ---------- To contribute to `dicteval`: 1. Clone this repository and `cd` into it 2. Install dev dependencies with [pipenv](https://github.com/pypa/pipenv) ```bash pipenv install --dev ``` 3. Create a branch, like `git checkout -b [feature_name]` 4. Git commit changes 5. Pull request License ------- This software is licensed under MIT license. Platform: UNKNOWN Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: >=3.7.0 dicteval-0.0.6/README.rst0000644000076500000240000000733513364254757015756 0ustar osantanastaff00000000000000dicteval ======== Library to evaluate expressions in dict/json objects. Requirements ------------ * Python 3.6+ Basic Usage ----------- Module ``dicteval`` will evaluate basic types with no modifications but it will evaluate dicts (or json objects) containing keys started with ``=`` (equal) symbol as an expression: >>> from dicteval import dicteval >>> dicteval(3) 3 >>> dicteval([3, 5]) [3, 5] >>> dicteval((5, 3)) [5, 3] >>> dicteval({"=sum": [3, 5]}) 8 >>> dicteval({"=": 5}) # = symbol alone is a 'nop' function 5 You can provide a dictionary with context to be used during evaluation process. >>> dicteval({"=": "!{var}"}, context={"var": 1.0}) 1.0 You can also wrap your string content with ``@{}`` to force a Python ``eval()`` with the context provided: >>> dicteval({"=sum": [3, "@{var + 2}"]}, context={"var": 3}) 8 .. warning:: This functionality will be removed (or changed) in future releases for security reasons. Functions --------- You can use the following builtin functions in your expressions: Function ``=any`` ''''''''''''''''' Returns ``True`` if any element of sequence is true. >>> dicteval({"=any": [1, 2, 3]}) True >>> dicteval({"=any": [0, 0]}) False Function ``=eq`` '''''''''''''''' Returns ``True`` if all elements of sequence are equals: >>> dicteval({"=eq": [1, 1, 1, 1]}) True Function ``=if`` '''''''''''''''' Evaluates condition and returns first value if true, otherwise, returns second value. If no false value is supplied, it is assumed to be ``None``. >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 6}) 'yes' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 4}) 'no' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes"]}, context={"var": 4}) Function ``=neq`` ''''''''''''''''' Returns ``True`` if elements of sequence are different: >>> dicteval({"=neq": [1, 1, 1, 5]}) True Function ``=`` (or ``nop``) ''''''''''''''''''''''''''' Returns the same values passed as arguments: >>> dicteval({"=": [1, 2, 3, 4]}) [1, 2, 3, 4] >>> dicteval({"=nop": "spam"}) 'spam' Function ``=not`` ''''''''''''''''' Returns the boolean inverse of argument: >>> dicteval({"=not": False}) True >>> dicteval({"=not": True}) False >>> dicteval({"=not": None}) True >>> dicteval({"=not": "XYZ"}) False Function ``=sum`` ''''''''''''''''' Returns a number with the sum of arguments: >>> dicteval({"=sum": [3, 5]}) 8 Function ``=mul`` ''''''''''''''''' Returns a number with the product of arguments: >>> dicteval({"=mul": [3, 5]}) 15 Function ``=all`` ''''''''''''''''' Return True if all elements of the iterable are true (or if the iterable is empty) >>> dicteval({"=all": (True, False)}) False >>> dicteval({"=all": (True, True)}) True Function ``=divmod`` '''''''''''''''''''' Returns a tuple containing the quotient and remainder after division: >>> dicteval({"=divmod": [8,3]}) (2, 2) >>> dicteval({"=divmod": [7.5,2.5]}) (3.0, 0.0) Function ``=zip`` ''''''''''''''''' Return list of aggregate tuples constructed from elements of multiple iterables. >>> dicteval({"=zip": [[1, 2, 3], [4, 5], [6, 7, 8, 9]]}) [(1, 4, 6), (2, 5, 7)] To Do ----- - Add more functions to the builtin language Contribute ---------- To contribute to `dicteval`: 1. Clone this repository and `cd` into it 2. Install dev dependencies with [pipenv](https://github.com/pypa/pipenv) ```bash pipenv install --dev ``` 3. Create a branch, like `git checkout -b [feature_name]` 4. Git commit changes 5. Pull request License ------- This software is licensed under MIT license. dicteval-0.0.6/dicteval/0000755000076500000240000000000013364255306016041 5ustar osantanastaff00000000000000dicteval-0.0.6/dicteval/__init__.py0000644000076500000240000000710513364253165020156 0ustar osantanastaff00000000000000import functools import json import operator import re from .exceptions import FunctionNotFound class LanguageSpecification: def __getitem__(self, item): if not item: item = "nop" if item.startswith('map'): item = "map" if item.startswith('filter'): item = "filter" try: return getattr(self, f"function_{item}") except AttributeError: raise FunctionNotFound(f"Function {item} not found.") class BuiltinLanguage(LanguageSpecification): def function_any(self, value, evaluator, context): return any(evaluator(v, context) for v in value) def function_all(self, value, evaluator, context): return all(evaluator(v, context) for v in value) def function_eq(self, value, evaluator, context): value = [evaluator(v, context) for v in value] return not value or value.count(value[0]) == len(value) def function_if(self, value, evaluator, context): values = [evaluator(v, context) for v in value] condition, t = values[0:2] f = values[2] if len(values) > 2 else None return t if condition else f def function_neq(self, value, evaluator, context): return not self.function_eq(value, evaluator, context) def function_nop(self, value, evaluator, context): return evaluator(value, context) def function_not(self, value, evaluator, context): return not evaluator(value, context) def function_sum(self, value, evaluator, context): return sum(evaluator(v, context) for v in value) def function_mul(self, value, evaluator, context): return functools.reduce(operator.mul, (evaluator(v, context) for v in value)) def function_divmod(self, value, evaluator, context): return divmod(*evaluator(value, context)) def function_map(self, func, value, evaluator, context): return [func(e) for e in [evaluator(v, context) for v in value]] def function_filter(self, func, value, evaluator, context): return list(filter(func, (evaluator(v, context) for v in value))) def function_zip(self, value, evaluator, context): lists = [evaluator(v, context) for v in value] return list(zip(*lists)) class Evaluator: def __init__(self, language_spec): self.language = language_spec() def __call__(self, expr, context=None): if context is None: context = {} if isinstance(expr, dict): expression_keys = [k for k in expr if k.startswith("=")] if len(expression_keys) != 1: raise ValueError("Invalid expression") key = expression_keys[0] value = expr[key] if isinstance(value, dict): value = self(value, context) func = self.language[key[1:]] if func.__name__ in ['function_map', 'function_filter']: coll_func = re.search(r'(map|filter)\((.*)\)', key).groups()[1] return func(eval(coll_func), value, self, context) return func(value, self, context) if isinstance(expr, (list, tuple)): return [self(v, context) for v in expr] # TODO: implement a safe eval here if isinstance(expr, str): if expr.startswith("@{") and expr.endswith("}"): return eval(expr[2:-1], {}, context) if expr.startswith("!{") and expr.endswith("}"): return context[expr[2:-1]] return expr dicteval = Evaluator(BuiltinLanguage) def jsoneval(string): return dicteval(json.loads(string)) dicteval-0.0.6/dicteval/exceptions.py0000644000076500000240000000014713263714261020574 0ustar osantanastaff00000000000000class EvaluationException(Exception): pass class FunctionNotFound(EvaluationException): pass dicteval-0.0.6/dicteval.egg-info/0000755000076500000240000000000013364255306017533 5ustar osantanastaff00000000000000dicteval-0.0.6/dicteval.egg-info/PKG-INFO0000644000076500000240000001355013364255306020634 0ustar osantanastaff00000000000000Metadata-Version: 1.2 Name: dicteval Version: 0.0.6 Summary: Evaluate expressions in dict/json objects Home-page: https://github.com/osantana/dicteval Author: Osvaldo Santana Neto Author-email: dicteval@osantana.me License: MIT Description: dicteval ======== Library to evaluate expressions in dict/json objects. Requirements ------------ * Python 3.6+ Basic Usage ----------- Module ``dicteval`` will evaluate basic types with no modifications but it will evaluate dicts (or json objects) containing keys started with ``=`` (equal) symbol as an expression: >>> from dicteval import dicteval >>> dicteval(3) 3 >>> dicteval([3, 5]) [3, 5] >>> dicteval((5, 3)) [5, 3] >>> dicteval({"=sum": [3, 5]}) 8 >>> dicteval({"=": 5}) # = symbol alone is a 'nop' function 5 You can provide a dictionary with context to be used during evaluation process. >>> dicteval({"=": "!{var}"}, context={"var": 1.0}) 1.0 You can also wrap your string content with ``@{}`` to force a Python ``eval()`` with the context provided: >>> dicteval({"=sum": [3, "@{var + 2}"]}, context={"var": 3}) 8 .. warning:: This functionality will be removed (or changed) in future releases for security reasons. Functions --------- You can use the following builtin functions in your expressions: Function ``=any`` ''''''''''''''''' Returns ``True`` if any element of sequence is true. >>> dicteval({"=any": [1, 2, 3]}) True >>> dicteval({"=any": [0, 0]}) False Function ``=eq`` '''''''''''''''' Returns ``True`` if all elements of sequence are equals: >>> dicteval({"=eq": [1, 1, 1, 1]}) True Function ``=if`` '''''''''''''''' Evaluates condition and returns first value if true, otherwise, returns second value. If no false value is supplied, it is assumed to be ``None``. >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 6}) 'yes' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes", "no"]}, context={"var": 4}) 'no' >>> dicteval({"=if": [{"=": "@{var > 5}"}, "yes"]}, context={"var": 4}) Function ``=neq`` ''''''''''''''''' Returns ``True`` if elements of sequence are different: >>> dicteval({"=neq": [1, 1, 1, 5]}) True Function ``=`` (or ``nop``) ''''''''''''''''''''''''''' Returns the same values passed as arguments: >>> dicteval({"=": [1, 2, 3, 4]}) [1, 2, 3, 4] >>> dicteval({"=nop": "spam"}) 'spam' Function ``=not`` ''''''''''''''''' Returns the boolean inverse of argument: >>> dicteval({"=not": False}) True >>> dicteval({"=not": True}) False >>> dicteval({"=not": None}) True >>> dicteval({"=not": "XYZ"}) False Function ``=sum`` ''''''''''''''''' Returns a number with the sum of arguments: >>> dicteval({"=sum": [3, 5]}) 8 Function ``=mul`` ''''''''''''''''' Returns a number with the product of arguments: >>> dicteval({"=mul": [3, 5]}) 15 Function ``=all`` ''''''''''''''''' Return True if all elements of the iterable are true (or if the iterable is empty) >>> dicteval({"=all": (True, False)}) False >>> dicteval({"=all": (True, True)}) True Function ``=divmod`` '''''''''''''''''''' Returns a tuple containing the quotient and remainder after division: >>> dicteval({"=divmod": [8,3]}) (2, 2) >>> dicteval({"=divmod": [7.5,2.5]}) (3.0, 0.0) Function ``=zip`` ''''''''''''''''' Return list of aggregate tuples constructed from elements of multiple iterables. >>> dicteval({"=zip": [[1, 2, 3], [4, 5], [6, 7, 8, 9]]}) [(1, 4, 6), (2, 5, 7)] To Do ----- - Add more functions to the builtin language Contribute ---------- To contribute to `dicteval`: 1. Clone this repository and `cd` into it 2. Install dev dependencies with [pipenv](https://github.com/pypa/pipenv) ```bash pipenv install --dev ``` 3. Create a branch, like `git checkout -b [feature_name]` 4. Git commit changes 5. Pull request License ------- This software is licensed under MIT license. Platform: UNKNOWN Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: >=3.7.0 dicteval-0.0.6/dicteval.egg-info/SOURCES.txt0000644000076500000240000000033513364255306021420 0ustar osantanastaff00000000000000LICENSE MANIFEST.in README.rst setup.cfg setup.py dicteval/__init__.py dicteval/exceptions.py dicteval.egg-info/PKG-INFO dicteval.egg-info/SOURCES.txt dicteval.egg-info/dependency_links.txt dicteval.egg-info/top_level.txtdicteval-0.0.6/dicteval.egg-info/dependency_links.txt0000644000076500000240000000000113364255306023601 0ustar osantanastaff00000000000000 dicteval-0.0.6/dicteval.egg-info/top_level.txt0000644000076500000240000000001113364255306022255 0ustar osantanastaff00000000000000dicteval dicteval-0.0.6/setup.cfg0000644000076500000240000000022313364255306016064 0ustar osantanastaff00000000000000[aliases] test = pytest [tool:pytest] addopts = --verbose --doctest-glob='*.rst' python_files = tests/*.py [egg_info] tag_build = tag_date = 0 dicteval-0.0.6/setup.py0000644000076500000240000000231613364255137015764 0ustar osantanastaff00000000000000#!/usr/bin/env python import io import os from setuptools import find_packages, setup NAME = 'dicteval' DESCRIPTION = 'Evaluate expressions in dict/json objects' URL = 'https://github.com/osantana/dicteval' EMAIL = 'dicteval@osantana.me' AUTHOR = 'Osvaldo Santana Neto' REQUIRES_PYTHON = '>=3.7.0' VERSION = "0.0.6" here = os.path.abspath(os.path.dirname(__file__)) with io.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: long_description = '\n' + f.read() setup( name=NAME, version=VERSION, description=DESCRIPTION, long_description=long_description, author=AUTHOR, author_email=EMAIL, python_requires=REQUIRES_PYTHON, url=URL, packages=find_packages(exclude=('tests',)), install_requires=[], include_package_data=True, license='MIT', classifiers=[ 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ], setup_requires=['pytest-runner'], tests_require=['pytest'], )